From 96ad538de9c3d4a4808f029c61288bf1930e27ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kre=20Solberg?= <andreas.solberg@uninett.no> Date: Mon, 28 Jan 2008 12:30:36 +0000 Subject: [PATCH] Implemented more efficient storage of AuthnRequests in session. Instead of caching the complete request object, we now cache an assoc array with the neccessary parameters. Both for SAML 2.0 and Shib 1.3. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@200 44740490-163a-0410-bde0-09ae8108e29a --- config/config-template.php | 4 + lib/SimpleSAML/Session.php | 88 ++++++++++++--- lib/SimpleSAML/XML/SAML20/AuthnRequest.php | 31 ++---- lib/SimpleSAML/XML/SAML20/AuthnResponse.php | 39 +++---- lib/SimpleSAML/XML/Shib13/AuthnRequest.php | 38 ++----- www/saml2/idp/SSOService.php | 101 ++++++++++++------ www/saml2/sp/AssertionConsumerService.php | 2 +- www/shib13/idp/SSOService.php | 112 +++++++++++++++----- www/shib13/sp/initSSO.php | 13 +-- 9 files changed, 266 insertions(+), 162 deletions(-) diff --git a/config/config-template.php b/config/config-template.php index dfb80660c..5f34ed762 100644 --- a/config/config-template.php +++ b/config/config-template.php @@ -66,7 +66,11 @@ $config = array ( * cookies both at the SP and the IdP exceeds this duration. */ 'session.duration' => 8 * (60*60), // 8 hours. + 'session.requestcache' => 4 * (60*60), // 4 hours + /* + * Languages available and what language is default + */ 'language.available' => array('en', 'no'), 'language.default' => 'en', diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index 4b85b4b54..3bf9ff8c1 100644 --- a/lib/SimpleSAML/Session.php +++ b/lib/SimpleSAML/Session.php @@ -1,6 +1,4 @@ <?php - - /** * The Session class holds information about a user session, and everything attached to it. * @@ -32,10 +30,19 @@ class SimpleSAML_Session { const STATE_LOGOUTINPROGRESS = 2; const STATE_LOGGEDOUT = 3; + /** + * This variable holds the instance of the session - Singleton approach. + */ private static $instance = null; + /** + * The track id is a new random unique identifier that is generate for each session. + * This is used in the debug logs and error messages to easily track more information + * about what went wrong. + */ private $trackid = 0; + private $configuration = null; private $authnrequests = array(); @@ -60,8 +67,13 @@ class SimpleSAML_Session { // Session duration parameters private $sessionstarted = null; private $sessionduration = null; + + private $dirty = false; + - // private constructor restricts instantiaton to getInstance() + /** + * private constructor restricts instantiaton to getInstance() + */ private function __construct($protocol, SimpleSAML_XML_AuthnResponse $message = null, $authenticated = true) { $this->configuration = SimpleSAML_Configuration::getInstance(); @@ -96,6 +108,7 @@ class SimpleSAML_Session { $sh = SimpleSAML_SessionHandler::getSessionHandler(); if($sh->get('SimpleSAMLphp_SESSION') !== NULL) { self::$instance = $sh->get('SimpleSAMLphp_SESSION'); + self::$instance->dirty = false; return self::$instance; } @@ -178,22 +191,62 @@ class SimpleSAML_Session { } } - public function setShibAuthnRequest(SimpleSAML_XML_Shib13_AuthnRequest $req) { - $this->shibauthreq = $req; - } + - public function getShibAuthnRequest() { - return $this->shibauthreq; - } + + /** + * This method retrieves from session a cache of a specific Authentication Request + * The complete request is not stored, instead the values that will be needed later + * are stored in an assoc array. + * + * @param $protocol saml2 or shib13 + * @param $requestid The request id used as a key to lookup the cache. + * + * @return Returns an assoc array of cached variables associated with the + * authentication request. + */ + public function getAuthnRequest($protocol, $requestid) { + if (isset($this->authnrequests[$protocol])) { + /* + * Traverse all cached authentication requests in this session for this user using this protocol + */ + foreach ($this->authnrequests[$protocol] AS $id => $cache) { + /* + * If any of the cached requests is elder than the session.requestcache duration, then just + * simply delete it :) + */ + if ($cache['date'] < $this->configuration->getValue('session.requestcache', time() - (4*60*60) )) + unset($this->authnrequests[$protocol][$id]); + } + } + /* + * Then look if the request id that was requested exists, if so return it. + */ + if (isset($this->authnrequests[$protocol][$requestid])) { + return $this->authnrequests[$protocol][$requestid]; + } - public function setAuthnRequest($requestid, SimpleSAML_XML_SAML20_AuthnRequest $xml) { - $this->authnrequests[$requestid] = $xml; + /* + * Could not find requested ID. Throw an error. Could be that it is never set, or that it is deleted due to age. + */ + throw new Exception('Could not find cached version of authentication request with ID ' . $requestid . ' (' . $protocol . ')'); } - public function getAuthnRequest($requestid) { - return $this->authnrequests[$requestid]; + /** + * This method sets a cached assoc array to the authentication request cache storage. + * + * @param $protocol saml2 or shib13 + * @param $requestid The request id used as a key to lookup the cache. + * @param $cache The assoc array that will be stored. + */ + public function setAuthnRequest($protocol, $requestid, array $cache) { + $cache['date'] = time(); + $this->authnrequests[$protocol][$requestid] = $cache; + } + + public function setAuthnResponse(SimpleSAML_XML_AuthnResponse $xml) { $this->authnresponse = $xml; } @@ -294,7 +347,14 @@ class SimpleSAML_Session { public function setAttribute($name, $value) { $this->attributes[$name] = $value; } - + + + /** + * Is this session modified since loaded? + */ + public function isModified() { + return $this->dirty; + } } ?> \ No newline at end of file diff --git a/lib/SimpleSAML/XML/SAML20/AuthnRequest.php b/lib/SimpleSAML/XML/SAML20/AuthnRequest.php index ead9afa38..b53a18e23 100644 --- a/lib/SimpleSAML/XML/SAML20/AuthnRequest.php +++ b/lib/SimpleSAML/XML/SAML20/AuthnRequest.php @@ -1,21 +1,15 @@ <?php - - -/** - * SimpleSAMLphp - * - * PHP versions 4 and 5 - * - * LICENSE: See the COPYING file included in this distribution. - * - * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> - */ require_once('SimpleSAML/Configuration.php'); require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php'); /** - * Configuration of SimpleSAMLphp + * The Shibboleth 1.3 Authentication Request. Not part of SAML 1.1, + * but an extension using query paramters no XML. + * + * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> + * @package simpleSAMLphp + * @version $Id$ */ class SimpleSAML_XML_SAML20_AuthnRequest { @@ -27,7 +21,7 @@ class SimpleSAML_XML_SAML20_AuthnRequest { private $relayState = null; - const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0'; + const PROTOCOL = 'saml2'; function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_Metadata_MetaDataStorageHandler $metadatastore) { @@ -110,7 +104,7 @@ class SimpleSAML_XML_SAML20_AuthnRequest { return $requestid; */ } - + /* public function createSession() { @@ -122,15 +116,10 @@ class SimpleSAML_XML_SAML20_AuthnRequest { } $session->setAuthnRequest($this->getRequestID(), $this); - - /* - if (isset($this->relayState)) { - $session->setRelayState($this->relayState); - } - */ + return $session; } - + */ public function generate($spentityid, $destination) { $md = $this->metadata->getMetaData($spentityid); diff --git a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php index 65ed360eb..1876ebc2a 100644 --- a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php +++ b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php @@ -24,14 +24,6 @@ require_once('xmlseclibs.php'); */ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse { - private $configuration = null; - private $metadata = 'default.php'; - - private $message = null; - private $dom; - private $relayState = null; - - private $validIDs = null; const PROTOCOL = 'urn:oasis:names:tc:SAML:2.0'; @@ -105,12 +97,15 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse { throw new Exception("Unable to validate Signature"); } + foreach ($refids AS $key => $value) { + $refids[$key] = str_replace('#', '', $value); + } + $this->validIDs = $refids; return true; } - - + function validateCertFingerprint($objKey) { @@ -229,9 +224,7 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse { $end = $node->getAttribute("NotOnOrAfter"); if (! SimpleSAML_Utilities::checkDateConditions($start, $end)) { - error_log( " Date check failed ... (from $start to $end)"); - - return $attributes; + throw new Exception("Date check failed (between $start and $end). Check if the clocks on the SP and IdP are synchronized. Alternatively you can get this message, when you move back in history or refresh an old page."); } } @@ -332,12 +325,12 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse { } - /* This function retrieves the ID of the request this response is a + /** + * This function retrieves the ID of the request this response is a * response to. This ID is stored in the InResponseTo attribute of the * top level DOM element. * - * Returns: - * The ID of the request this response is a response to, or NULL if + * @return The ID of the request this response is a response to, or NULL if * we don't know. */ public function getInResponseTo() { @@ -466,17 +459,16 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse { } - /* This function converts an array of attribute values into an + /** + * This function converts an array of attribute values into an * encoded saml:Attribute element which should go into the * AuthnResponse. The data can optionally be base64 encoded. * - * Parameters: - * $name Name of this attribute. - * $values Array with the values of this attribute. - * $base64 Enable base64 encoding of attribute values. + * @param $name Name of this attribute. + * @param $values Array with the values of this attribute. + * @param $base64 Enable base64 encoding of attribute values. * - * Returns: - * String containing the encoded saml:attribute value for this + * @return String containing the encoded saml:attribute value for this * attribute. */ private static function enc_attribute($name, $values, $base64 = false) { @@ -495,7 +487,6 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse { $text . '</saml:AttributeValue>'; } - $ret .= '</saml:Attribute>'; return $ret; diff --git a/lib/SimpleSAML/XML/Shib13/AuthnRequest.php b/lib/SimpleSAML/XML/Shib13/AuthnRequest.php index 053319c41..1fe6972aa 100644 --- a/lib/SimpleSAML/XML/Shib13/AuthnRequest.php +++ b/lib/SimpleSAML/XML/Shib13/AuthnRequest.php @@ -1,21 +1,15 @@ <?php - -/** - * SimpleSAMLphp - * - * PHP versions 4 and 5 - * - * LICENSE: See the COPYING file included in this distribution. - * - * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> - */ - require_once('SimpleSAML/Configuration.php'); require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php'); /** - * Configuration of SimpleSAMLphp + * The Shibboleth 1.3 Authentication Request. Not part of SAML 1.1, + * but an extension using query paramters no XML. + * + * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> + * @package simpleSAMLphp + * @version $Id$ */ class SimpleSAML_XML_Shib13_AuthnRequest { @@ -29,7 +23,7 @@ class SimpleSAML_XML_Shib13_AuthnRequest { private $requestid = null; - const PROTOCOL = 'shibboleth'; + const PROTOCOL = 'shib13'; function __construct(SimpleSAML_Configuration $configuration, SimpleSAML_Metadata_MetaDataStorageHandler $metadatastore) { @@ -83,25 +77,7 @@ class SimpleSAML_XML_Shib13_AuthnRequest { public function getRequestID() { return $this->requestid; } - - public function createSession() { - - $session = SimpleSAML_Session::getInstance(); - - if (!isset($session)) { - SimpleSAML_Session::init(self::PROTOCOL, null, false); - $session = SimpleSAML_Session::getInstance(); - } - $session->setShibAuthnRequest($this); - - /* - if (isset($this->relayState)) { - $session->setRelayState($this->relayState); - } - */ - return $session; - } public function createRedirect($destination) { $idpmetadata = $this->metadata->getMetaData($destination, 'shib13-idp-remote'); diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php index 7c2b82aa5..31d590aa5 100644 --- a/www/saml2/idp/SSOService.php +++ b/www/saml2/idp/SSOService.php @@ -1,9 +1,16 @@ <?php - +/** + * The SSOService is part of the SAML 2.0 IdP code, and it receives incomming Authentication Requests + * from a SAML 2.0 SP, parses, and process it, and then authenticates the user and sends the user back + * to the SP with an Authentication Response. + * + * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> + * @package simpleSAMLphp + * @version $Id$ + */ require_once('../../../www/_include.php'); - require_once('SimpleSAML/Utilities.php'); require_once('SimpleSAML/Session.php'); require_once('SimpleSAML/Logger.php'); @@ -29,7 +36,14 @@ $requestid = null; $logger->log(LOG_INFO, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'EVENT', 'Access', 'Accessing SAML 2.0 IdP endpoint SSOService'); - +/* + * If the SAMLRequest query parameter is set, we got an incomming Authentication Request + * at this interface. + * + * In this case, what we should do is to process the request and set the neccessary information + * from the request into the session object to be used later. + * + */ if (isset($_GET['SAMLRequest'])) { @@ -37,16 +51,25 @@ if (isset($_GET['SAMLRequest'])) { $binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata); $authnrequest = $binding->decodeRequest($_GET); - $session = $authnrequest->createSession(); + //$session = $authnrequest->createSession(); $requestid = $authnrequest->getRequestID(); + /* + * Create an assoc array of the request to store in the session cache. + */ + $requestcache = array( + 'Issuer' => $authnrequest->getIssuer() + ); + if ($relaystate = $authnrequest->getRelayState() ) + $requestcache['RelayState'] = $relaystate; + + $session->setAuthnRequest('saml2', $requestid, $requestcache); + if ($binding->validateQuery($authnrequest->getIssuer(),'IdP')) { $logger->log(LOG_INFO, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'AuthnRequest', $requestid, 'Valid signature found'); } - $session->setAuthnRequest($requestid, $authnrequest); - $logger->log(LOG_NOTICE, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'AuthnRequest', array($authnrequest->getIssuer(), $requestid), 'Incomming Authentication request'); @@ -63,19 +86,26 @@ if (isset($_GET['SAMLRequest'])) { exit(0); } +/* + * If we did not get an incomming Authenticaiton Request, we need a RequestID parameter. + * + * The RequestID parameter is used to retrieve the information stored in the session object + * related to the request that was received earlier. Usually the request is processed with + * code above, then the user is redirected to some login module, and when successfully authenticated + * the user isredirected back to this endpoint, and then the user will need to have the RequestID + * parmeter attached. + */ } elseif(isset($_GET['RequestID'])) { try { $requestid = $_GET['RequestID']; - $session = SimpleSAML_Session::getInstance(); - $authnrequest = $session->getAuthnRequest($requestid); + $requestcache = $session->getAuthnRequest('saml2', $requestid); $logger->log(LOG_INFO, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'EVENT', $requestid, 'Got incomming RequestID'); - - if (!$authnrequest) throw new Exception('Could not retrieve cached RequestID = ' . $requestid); + if (!$requestcache) throw new Exception('Could not retrieve cached RequestID = ' . $requestid); } catch(Exception $exception) { @@ -90,24 +120,31 @@ if (isset($_GET['SAMLRequest'])) { } - - /* - $authnrequest = new SimpleSAML_XML_SAML20_AuthnRequest($config, $metadata); - $authnrequest->setXML($authnrequestXML); - */ - - } else { - - echo 'You must either provide a SAML Request message or a RequestID on this interface.'; + /* + * We did neither get a request or a requestID as a parameter. Then throw an error. + */ + $et = new SimpleSAML_XHTML_Template($config, 'error.php'); + + $et->data['header'] = 'No parameters found'; + $et->data['message'] = 'You must either provide a SAML Request message or a RequestID on this interface.'; + $et->data['e'] = $exception; + + $et->show(); exit(0); - } - - +/* + * As we have passed the code above, we have an accociated request that is already processed. + * + * Now we check whether we have a authenticated session. If we do not have an authenticated session, + * we look up in the metadata of the IdP, to see what authenticaiton module to use, then we redirect + * the user to the authentication module, to authenticate. Later the user is redirected back to this + * endpoint - then the session is authenticated and set, and the user is redirected back with a RequestID + * parameter so we can retrieve the cached information from the request. + */ if (!$session->isAuthenticated() ) { $logger->log(LOG_NOTICE, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'AuthNext', $idpmeta['auth'], @@ -119,12 +156,16 @@ if (!$session->isAuthenticated() ) { SimpleSAML_Utilities::redirect($authurl, array('RelayState' => $relaystate)); + +/* + * We got an request, and we hav a valid session. Then we send an AuthenticationResponse back to the + * service. + */ } else { try { - - $spentityid = $authnrequest->getIssuer(); + $spentityid = $requestcache['Issuer']; $spmetadata = $metadata->getMetaData($spentityid, 'saml20-sp-remote'); /* @@ -151,19 +192,16 @@ if (!$session->isAuthenticated() ) { $logger->log(LOG_NOTICE, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'ConsentOK', '-', 'Got consent from user'); - } } // Adding this service provider to the list of sessions. + // Right now the list is used for SAML 2.0 only. $session->add_sp_session($spentityid); - - $logger->log(LOG_NOTICE, $session->getTrackID(), 'SAML2.0', 'IdP.SSOService', 'AuthnResponse', $spentityid, 'Sending back AuthnResponse'); - /* * Filtering attributes. @@ -185,9 +223,9 @@ if (!$session->isAuthenticated() ) { // Sending the AuthNResponse using HTTP-Post SAML 2.0 binding $httppost = new SimpleSAML_Bindings_SAML20_HTTPPost($config, $metadata); $httppost->sendResponse($authnResponseXML, - $idpentityid, $authnrequest->getIssuer(), $authnrequest->getRelayState()); - - + $idpentityid, $spentityid, + isset($requestcache['RelayState']) ? $requestcache['RelayState'] : null + ); } catch(Exception $exception) { @@ -198,7 +236,6 @@ if (!$session->isAuthenticated() ) { $et->data['e'] = $exception; $et->show(); - } } diff --git a/www/saml2/sp/AssertionConsumerService.php b/www/saml2/sp/AssertionConsumerService.php index 3b327e4bc..d1d5da804 100644 --- a/www/saml2/sp/AssertionConsumerService.php +++ b/www/saml2/sp/AssertionConsumerService.php @@ -44,7 +44,7 @@ try { if (isset($relayState)) { SimpleSAML_Utilities::redirect($relayState); } else { - echo 'Could not find RelayState parameter, you are stucked here.'; + throw new Exception('Could not find RelayState parameter, you are stucked here.'); } } else { throw new Exception('Unkown error. Could not get session.'); diff --git a/www/shib13/idp/SSOService.php b/www/shib13/idp/SSOService.php index 44c3e6ce1..f5ce87b63 100644 --- a/www/shib13/idp/SSOService.php +++ b/www/shib13/idp/SSOService.php @@ -1,11 +1,19 @@ <?php - +/** + * The SSOService is part of the Shibboleth 1.3 IdP code, and it receives incomming Authentication Requests + * from a Shibboleth 1.3 SP, parses, and process it, and then authenticates the user and sends the user back + * to the SP with an Authentication Response. + * + * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> + * @package simpleSAMLphp + * @version $Id$ + */ require_once('../../../www/_include.php'); - require_once('SimpleSAML/Utilities.php'); require_once('SimpleSAML/Session.php'); +require_once('SimpleSAML/Logger.php'); require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php'); require_once('SimpleSAML/XML/AttributeFilter.php'); require_once('SimpleSAML/XML/Shib13/AuthnRequest.php'); @@ -17,14 +25,25 @@ require_once('SimpleSAML/XHTML/Template.php'); $config = SimpleSAML_Configuration::getInstance(); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); +$session = SimpleSAML_Session::getInstance(true); + +$logger = new SimpleSAML_Logger(); $idpentityid = $metadata->getMetaDataCurrentEntityID('shib13-idp-hosted'); $idpmeta = $metadata->getMetaDataCurrent('shib13-idp-hosted'); $requestid = null; -$session = null; +$logger->log(LOG_INFO, $session->getTrackID(), 'Shib1.3', 'IdP.SSOService', 'EVENT', 'Access', 'Accessing Shibboleth 1.3 IdP endpoint SSOService'); +/* + * If the shire query parameter is set, we got an incomming Authentication Request + * at this interface. + * + * In this case, what we should do is to process the request and set the neccessary information + * from the request into the session object to be used later. + * + */ if (isset($_GET['shire'])) { @@ -32,13 +51,25 @@ if (isset($_GET['shire'])) { $authnrequest = new SimpleSAML_XML_Shib13_AuthnRequest($config, $metadata); $authnrequest->parseGet($_GET); - $session = $authnrequest->createSession(); + //$session = $authnrequest->createSession(); $requestid = $authnrequest->getRequestID(); //$session->setShibAuthnRequest($authnrequest); - + + + /* + * Create an assoc array of the request to store in the session cache. + */ + $requestcache = array( + 'Issuer' => $authnrequest->getIssuer(), + 'shire' => $authnrequest->getShire(), + ); + if ($relaystate = $authnrequest->getRelayState() ) + $requestcache['RelayState'] = $relaystate; + + $session->setAuthnRequest('shib13', $requestid, $requestcache); } catch(Exception $exception) { @@ -50,21 +81,31 @@ if (isset($_GET['shire'])) { $et->data['e'] = $exception; $et->show(); - + exit(0); } -} elseif(isset($_GET['RequestID'])) { - - +/* + * If we did not get an incomming Authenticaiton Request, we need a RequestID parameter. + * + * The RequestID parameter is used to retrieve the information stored in the session object + * related to the request that was received earlier. Usually the request is processed with + * code above, then the user is redirected to some login module, and when successfully authenticated + * the user isredirected back to this endpoint, and then the user will need to have the RequestID + * parmeter attached. + */ +} elseif(isset($_GET['RequestID'])) { + try { $requestid = $_GET['RequestID']; - $session = SimpleSAML_Session::getInstance(); - $authnrequest = $session->getShibAuthnRequest(); + + $requestcache = $session->getAuthnRequest('shib13', $requestid); - if (!$authnrequest) throw new Exception('Could not retrieve cached RequestID = ' . $requestid); + $logger->log(LOG_INFO, $session->getTrackID(), 'Shib1.3', 'IdP.SSOService', 'EVENT', $requestid, 'Got incomming RequestID'); + if (!$requestcache) throw new Exception('Could not retrieve cached RequestID = ' . $requestid); + } catch(Exception $exception) { $et = new SimpleSAML_XHTML_Template($config, 'error.php'); @@ -74,33 +115,46 @@ if (isset($_GET['shire'])) { $et->data['e'] = $exception; $et->show(); - } - - - /* - $authnrequest = new SimpleSAML_XML_SAML20_AuthnRequest($config, $metadata); - $authnrequest->setXML($authnrequestXML); - */ - - } else { - - echo 'You must either provide a SAML Request message or a RequestID on this interface.'; + /* + * We did neither get a request or a requestID as a parameter. Then throw an error. + */ + $et = new SimpleSAML_XHTML_Template($config, 'error.php'); + + $et->data['header'] = 'No parameters found'; + $et->data['message'] = 'You must either provide a Shibboleth Request message or a RequestID on this interface.'; + $et->data['e'] = $exception; + + $et->show(); exit(0); } - +/* + * As we have passed the code above, we have an accociated request that is already processed. + * + * Now we check whether we have a authenticated session. If we do not have an authenticated session, + * we look up in the metadata of the IdP, to see what authenticaiton module to use, then we redirect + * the user to the authentication module, to authenticate. Later the user is redirected back to this + * endpoint - then the session is authenticated and set, and the user is redirected back with a RequestID + * parameter so we can retrieve the cached information from the request. + */ if (!$session->isAuthenticated() ) { $relaystate = SimpleSAML_Utilities::selfURLNoQuery() . '?RequestID=' . urlencode($requestid); $authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getValue('baseurlpath') . $idpmeta['auth'], 'RelayState=' . urlencode($relaystate)); SimpleSAML_Utilities::redirect($authurl); + + +/* + * We got an request, and we hav a valid session. Then we send an AuthenticationResponse back to the + * service. + */ } else { try { @@ -110,7 +164,7 @@ if (!$session->isAuthenticated() ) { //$session->setAttribute('eduPersonAffiliation', array('student')); - $spentityid = $authnrequest->getIssuer(); + $spentityid = $requestcache['Issuer']; $spmetadata = $metadata->getMetaData($spentityid, 'shib13-sp-remote'); /* @@ -130,7 +184,7 @@ if (!$session->isAuthenticated() ) { // Generating a Shibboleth 1.3 Response. $ar = new SimpleSAML_XML_Shib13_AuthnResponse($config, $metadata); - $authnResponseXML = $ar->generate($idpentityid, $authnrequest->getIssuer(), + $authnResponseXML = $ar->generate($idpentityid, $requestcache['Issuer'], $requestid, null, $filteredattributes); @@ -142,13 +196,13 @@ if (!$session->isAuthenticated() ) { //echo 'Relaystate[' . $authnrequest->getRelayState() . ']'; - $issuer = $authnrequest->getIssuer(); - $shire = $authnrequest->getShire(); + $issuer = $requestcache['Issuer']; + $shire = $requestcache['shire']; if ($issuer == null || $issuer == '') throw new Exception('Could not retrieve issuer of the AuthNRequest (ProviderID)'); $httppost->sendResponse($authnResponseXML, - $idpentityid, $issuer, $authnrequest->getRelayState(), $shire); + $idpentityid, $issuer, isset($requestcache['RelayState']) ? $requestcache['RelayState'] : null, $shire); } catch(Exception $exception) { diff --git a/www/shib13/sp/initSSO.php b/www/shib13/sp/initSSO.php index 106ae18f9..55a7723fb 100644 --- a/www/shib13/sp/initSSO.php +++ b/www/shib13/sp/initSSO.php @@ -8,9 +8,6 @@ require_once('SimpleSAML/Session.php'); require_once('SimpleSAML/XHTML/Template.php'); require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php'); require_once('SimpleSAML/XML/Shib13/AuthnRequest.php'); -//require_once('SimpleSAML/XML/SAML20/AuthnResponse.php'); -//require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php'); -//require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php'); $config = SimpleSAML_Configuration::getInstance(); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); @@ -41,9 +38,10 @@ try { exit(0); } + + if (!isset($session) || !$session->isValid() ) { - if ($idpentityid == null) { $returnURL = urlencode(SimpleSAML_Utilities::selfURL()); @@ -77,7 +75,6 @@ if (!isset($session) || !$session->isValid() ) { } else { - $relaystate = $session->getRelayState(); if (isset($relaystate) && !empty($relaystate)) { @@ -96,10 +93,6 @@ if (!isset($session) || !$session->isValid() ) { } -#print_r($metadata->getMetaData('sam.feide.no')); -#print_r($req); - -//echo 'Location: ' . $relaystate; -?> +?> \ No newline at end of file -- GitLab