From db4f7811dfdf51e07f72a8f37d2cb281e84a1b4f Mon Sep 17 00:00:00 2001 From: Jaime Perez <jaime.perez@uninett.no> Date: Fri, 27 Jun 2014 16:15:16 +0200 Subject: [PATCH] Fix #82 and #83. Make the checks for an IDPList happen only when we are the IdP authenticating the user, not an intermediate proxy. --- lib/SimpleSAML/IdP.php | 2 -- modules/saml/lib/Auth/Source/SP.php | 55 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php index d9b997dc6..119231a00 100644 --- a/lib/SimpleSAML/IdP.php +++ b/lib/SimpleSAML/IdP.php @@ -379,8 +379,6 @@ class SimpleSAML_IdP { if (isset($state['ForceAuthn']) && (bool)$state['ForceAuthn']) { /* Force authentication is in effect. */ $needAuth = TRUE; - } elseif (isset($state['saml:IDPList']) && sizeof($state['saml:IDPList']) > 0) { - $needAuth = !in_array($this->authSource->getAuthData('saml:sp:IdP'), $state['saml:IDPList'], TRUE); } else { $needAuth = !$this->isAuthenticated(); } diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php index a2b223588..a23cb0fe9 100644 --- a/modules/saml/lib/Auth/Source/SP.php +++ b/modules/saml/lib/Auth/Source/SP.php @@ -392,6 +392,61 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source { } + /** + * Re-authenticate an user. + * + * This function is called by the IdP to give the authentication source a chance to + * interact with the user even in the case when the user is already authenticated. + * + * @param array &$state Information about the current authentication. + */ + public function reauthenticate(array &$state) { + assert('is_array($state)'); + + $session = SimpleSAML_Session::getInstance(); + $data = $session->getAuthState($this->authId); + foreach ($data as $k => $v) { + $state[$k] = $v; + } + + // check if we have an IDPList specified in the request + if (isset($state['saml:IDPList']) && sizeof($state['saml:IDPList']) > 0 && + !in_array($state['saml:sp:IdP'], $state['saml:IDPList'], TRUE)) { + /* + * This is essentially wrong. The IdP used to authenticate the current session is not in the IDPList + * that we just received, so we are triggering authentication again against an IdP in the IDPList. This + * is fine if the user wants to, but we SHOULD offer the user to logout before proceeding. + * + * After successful authentication in a different IdP, the reauthPostLogin callback will be invoked, + * overriding the current session with a new one, associated with the new IdP. This will leave us in an + * inconsistent state, with several service providers with valid sessions they got from different IdPs. + * + * TODO: we need to offer the user the possibility to logout before blindly authenticating him again. + */ + $state['LoginCompletedHandler'] = array('sspmod_saml_Auth_Source_SP', 'reauthPostLogin'); + $this->authenticate($state); + } + } + + + /** + * Complete login operation after re-authenticating the user on another IdP. + * + * @param array $state The authentication state. + */ + public static function reauthPostLogin(array $state) { + assert('isset($state["ReturnCallback"])'); + + // Update session state + $session = SimpleSAML_Session::getInstance(); + $session->doLogin($state['saml:sp:AuthId'], SimpleSAML_Auth_Default::extractPersistentAuthState($state)); + + // resume the login process + call_user_func($state['ReturnCallback'], $state); + assert('FALSE'); + } + + /** * Start a SAML 2 logout operation. * -- GitLab