From ac90032707b7ab74c697cc62529768cdba96b193 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Tue, 1 Apr 2008 14:09:07 +0000 Subject: [PATCH] Add support for ForceAuthn on the IdP side. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@481 44740490-163a-0410-bde0-09ae8108e29a --- docs/source/simplesamlphp-idp.xml | 10 +++++ lib/SimpleSAML/Session.php | 16 ++++++++ lib/SimpleSAML/XML/SAML20/AuthnRequest.php | 30 ++++++++++++++ www/admin/metadata.php | 2 +- www/saml2/idp/SSOService.php | 46 ++++++++++++++++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) diff --git a/docs/source/simplesamlphp-idp.xml b/docs/source/simplesamlphp-idp.xml index 1c123bf4a..337411ad2 100644 --- a/docs/source/simplesamlphp-idp.xml +++ b/docs/source/simplesamlphp-idp.xml @@ -529,6 +529,16 @@ openssl x509 -req -days 60 -in server2.csr -signkey server2.key -out server2.crt <literal>true</literal>.</para> </glossdef> </glossentry> + + <glossentry> + <glossterm>ForceAuthn</glossterm> + + <glossdef> + <para>Set this <literal>true</literal> to force authentication + when receiving authentication requests from this SP. The default + is <literal>false</literal>.</para> + </glossdef> + </glossentry> </glosslist> </section> </section> diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index 997f8d3a2..8d689f0f3 100644 --- a/lib/SimpleSAML/Session.php +++ b/lib/SimpleSAML/Session.php @@ -335,6 +335,7 @@ class SimpleSAML_Session implements SimpleSAML_ModifiedInfo { $this->authenticated = $auth; if ($auth) { + $this->clearNeedAuthFlag(); $this->sessionstarted = time(); } else { /* Call logout handlers. */ @@ -473,6 +474,21 @@ class SimpleSAML_Session implements SimpleSAML_ModifiedInfo { $this->logout_handlers = array(); } + + /** + * This function iterates over all current authentication requests, and removes any 'NeedAuthentication' flags + * from them. + */ + private function clearNeedAuthFlag() { + foreach($this->authnrequests as &$cache) { + foreach($cache as &$request) { + if(array_key_exists('NeedAuthentication', $request)) { + $request['NeedAuthentication'] = FALSE; + } + } + } + } + } ?> \ No newline at end of file diff --git a/lib/SimpleSAML/XML/SAML20/AuthnRequest.php b/lib/SimpleSAML/XML/SAML20/AuthnRequest.php index 2b9f36a2e..4e4412f14 100644 --- a/lib/SimpleSAML/XML/SAML20/AuthnRequest.php +++ b/lib/SimpleSAML/XML/SAML20/AuthnRequest.php @@ -107,6 +107,36 @@ class SimpleSAML_XML_SAML20_AuthnRequest { } + /** + * This function retrieves the ForceAuthn flag from this authentication request. + * + * @return The ForceAuthn flag from this authentication request. + */ + public function getForceAuthn() { + $dom = $this->getDOM(); + if (empty($dom)) { + throw new Exception("Could not get message DOM in AuthnRequest object"); + } + + $root = $dom->documentElement; + + if(!$root->hasAttribute('ForceAuthn')) { + /* ForceAuthn defaults to false. */ + return FALSE; + } + + $fa = $root->getAttribute('ForceAuthn'); + if($fa === 'true') { + return TRUE; + } elseif($fa === 'false') { + return FALSE; + } else { + throw new Exception('Invalid value of ForceAuthn attribute in SAML2 AuthnRequest.'); + } + } + + + /** * Generate a new SAML 2.0 Authentication Request * diff --git a/www/admin/metadata.php b/www/admin/metadata.php index 53579c55a..50634e27f 100644 --- a/www/admin/metadata.php +++ b/www/admin/metadata.php @@ -67,7 +67,7 @@ try { foreach ($metalist AS $entityid => $mentry) { $results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry, array('entityid', 'AssertionConsumerService'), - array('SingleLogoutService', 'NameIDFormat', 'SPNameQualifier', 'base64attributes', 'simplesaml.nameidattribute', 'attributemap', 'attributealter', 'simplesaml.attributes', 'attributes', 'name', 'description','request.signing','certificate') + array('SingleLogoutService', 'NameIDFormat', 'SPNameQualifier', 'base64attributes', 'simplesaml.nameidattribute', 'attributemap', 'attributealter', 'simplesaml.attributes', 'attributes', 'name', 'description','request.signing','certificate', 'ForceAuthn') ); } $et->data['metadata.saml20-sp-remote'] = $results; diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php index c7ae11bbb..d7f44fd84 100644 --- a/www/saml2/idp/SSOService.php +++ b/www/saml2/idp/SSOService.php @@ -75,6 +75,41 @@ if (isset($_GET['SAMLRequest'])) { if ($relaystate = $authnrequest->getRelayState() ) $requestcache['RelayState'] = $relaystate; + + /* + * Handle the ForceAuthn option. + */ + + /* The default value is FALSE. */ + $forceAuthn = FALSE; + + $spentityid = $requestcache['Issuer']; + $spmetadata = $metadata->getMetaData($spentityid, 'saml20-sp-remote'); + if(array_key_exists('ForceAuthn', $spmetadata)) { + /* The ForceAuthn flag is set in the metadata for this SP. */ + $forceAuthn = $spmetadata['ForceAuthn']; + if(!is_bool($spmetadata['ForceAuthn'])) { + throw new Exception('The ForceAuthn option in the metadata for the sp [' . $spentityid . '] is not a boolean.'); + } + + if($spmetadata['ForceAuthn']) { + /* ForceAuthn enabled in the metadata for the SP. */ + $forceAuthn = TRUE; + } + } + + if($authnrequest->getForceAuthn()) { + /* The ForceAuthn flag was set to true in the authentication request. */ + $forceAuthn = TRUE; + } + + if($forceAuthn) { + /* ForceAuthn is enabled. Mark the request as needing authentication. This flag + * will be cleared by a call to setAuthenticated(TRUE, ...) to the current session. + */ + $requestcache['NeedAuthentication'] = TRUE; + } + $session->setAuthnRequest('saml2', $requestid, $requestcache); @@ -129,6 +164,17 @@ $authority = isset($idpmetadata['authority']) ? $idpmetadata['authority'] : NULL * parameter so we can retrieve the cached information from the request. */ if (!isset($session) || !$session->isValid($authority) ) { + /* We don't have a valid session. */ + $needAuth = TRUE; +} elseif (array_key_exists('NeedAuthentication', $requestcache) && $requestcache['NeedAuthentication']) { + /* We have a valid session, but ForceAuthn is on. */ + $needAuth = TRUE; +} else { + /* We have a valid session. */ + $needAuth = FALSE; +} + +if($needAuth) { SimpleSAML_Logger::info('SAML2.0 - IdP.SSOService: Will go to authentication module ' . $idpmetadata['auth']); -- GitLab