$authId, 'SimpleSAML_Auth_Default.Return' => $return, 'SimpleSAML_Auth_Default.ErrorURL' => $errorURL, 'LoginCompletedHandler' => array(get_class(), 'loginCompleted'), 'LogoutCallback' => array(get_class(), 'logoutCallback'), 'LogoutCallbackState' => array( 'SimpleSAML_Auth_Default.logoutSource' => $authId, ), )); if (is_string($return)) { $state['SimpleSAML_Auth_Default.ReturnURL'] = $return; } if ($errorURL !== NULL) { $state[SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL] = $errorURL; } $as = SimpleSAML_Auth_Source::getById($authId); if ($as === NULL) { throw new Exception('Invalid authentication source: ' . $authId); } try { $as->authenticate($state); } catch (SimpleSAML_Error_Exception $e) { SimpleSAML_Auth_State::throwException($state, $e); } catch (Exception $e) { $e = new SimpleSAML_Error_UnserializableException($e); SimpleSAML_Auth_State::throwException($state, $e); } self::loginCompleted($state); } /** * Extract the persistent authentication state from the state array. * * @param array $state The state after the login. * @return array The persistent authentication state. */ public static function extractPersistentAuthState(array &$state) { /* Save persistent authentication data. */ $persistentAuthState = array(); if (isset($state['IdP'])) { /* For backwards compatibility. */ $persistentAuthState['saml:sp:IdP'] = $state['IdP']; } if (isset($state['PersistentAuthData'])) { foreach ($state['PersistentAuthData'] as $key) { if (isset($state[$key])) { $persistentAuthState[$key] = $state[$key]; } } } /* Add those that should always be included. */ foreach (array('Attributes', 'Expire', 'LogoutState', 'AuthnInstant', 'RememberMe') as $a) { if (isset($state[$a])) { $persistentAuthState[$a] = $state[$a]; } } return $persistentAuthState; } /** * Called when a login operation has finished. * * @param array $state The state after the login. */ public static function loginCompleted($state) { assert('is_array($state)'); assert('array_key_exists("SimpleSAML_Auth_Default.Return", $state)'); assert('array_key_exists("SimpleSAML_Auth_Default.id", $state)'); assert('array_key_exists("Attributes", $state)'); assert('!array_key_exists("LogoutState", $state) || is_array($state["LogoutState"])'); $return = $state['SimpleSAML_Auth_Default.Return']; /* Save session state. */ $session = SimpleSAML_Session::getSessionFromRequest(); $session->doLogin($state['SimpleSAML_Auth_Default.id'], self::extractPersistentAuthState($state)); if (is_string($return)) { /* Redirect... */ SimpleSAML_Utilities::redirectTrustedURL($return); } else { call_user_func($return, $state); assert('FALSE'); } } /** * Start logout. * * This function starts a logout operation from the current authentication * source. This function will return if the logout operation does not * require a redirect. * * @param string $returnURL The URL we should redirect the user to after * logging out. No checking is performed on the URL, so make sure to verify * it on beforehand if the URL is obtained from user input. Refer to * SimpleSAML_Utilities::checkURLAllowed() for more information. * @param string|NULL $authority The authentication source we are logging * out from, or NULL to log out from the most recent. */ public static function initLogoutReturn($returnURL, $authority = NULL) { assert('is_string($returnURL)'); assert('is_string($authority) || is_null($authority)'); $session = SimpleSAML_Session::getSessionFromRequest(); if ($authority === NULL) { $authority = $session->getAuthority(); if ($authority === NULL) { /* Already logged out - nothing to do here. */ return; } } $state = $session->getAuthData($authority, 'LogoutState'); $session->doLogout($authority); $state['SimpleSAML_Auth_Default.ReturnURL'] = $returnURL; $state['LogoutCompletedHandler'] = array(get_class(), 'logoutCompleted'); $as = SimpleSAML_Auth_Source::getById($authority); if ($as === NULL) { /* The authority wasn't an authentication source... */ self::logoutCompleted($state); } $as->logout($state); } /** * Start logout. * * This function starts a logout operation from the current authentication * source. This function never returns. * * @param string $returnURL The URL we should redirect the user to after * logging out. No checking is performed on the URL, so make sure to verify * it on beforehand if the URL is obtained from user input. Refer to * SimpleSAML_Utilities::checkURLAllowed() for more information. * @param string|NULL $authority The authentication source we are logging * out from, or NULL to log out from the most recent. * @return void This function never returns. */ public static function initLogout($returnURL, $authority = NULL) { assert('is_string($returnURL)'); assert('is_string($authority) || is_null($authority)'); self::initLogoutReturn($returnURL, $authority); /* Redirect... */ SimpleSAML_Utilities::redirectTrustedURL($returnURL); } /** * Called when logout operation completes. * * This function never returns. * * @param array $state The state after the logout. */ public static function logoutCompleted($state) { assert('is_array($state)'); assert('array_key_exists("SimpleSAML_Auth_Default.ReturnURL", $state)'); $returnURL = $state['SimpleSAML_Auth_Default.ReturnURL']; /* Redirect... */ SimpleSAML_Utilities::redirectTrustedURL($returnURL); } /** * Called when the authentication source receives an external logout request. * * @param array $state State array for the logout operation. */ public static function logoutCallback($state) { assert('is_array($state)'); assert('array_key_exists("SimpleSAML_Auth_Default.logoutSource", $state)'); $source = $state['SimpleSAML_Auth_Default.logoutSource']; $session = SimpleSAML_Session::getSessionFromRequest(); $authId = $session->getAuthority(); if ($authId !== $source) { SimpleSAML_Logger::warning('Received logout from different authentication source ' . 'than the current. Current is ' . var_export($authId, TRUE) . '. Logout source is ' . var_export($source, TRUE) . '.'); return; } $session->doLogout(); } /** * Handle a unsolicited login operations. * * This function creates a session from the received information. It * will then redirect to the given URL. * * This is used to handle IdP initiated SSO. * * @param string $authId The id of the authentication source that received * the request. * @param array $state A state array. * @param string $redirectTo The URL we should redirect the user to after * updating the session. The function will check if the URL is allowed, so * there is no need to manually check the URL on beforehand. Please refer * to the 'trusted.url.domains' configuration directive for more * information about allowing (or disallowing) URLs. */ public static function handleUnsolicitedAuth($authId, array $state, $redirectTo) { assert('is_string($authId)'); assert('is_string($redirectTo)'); $session = SimpleSAML_Session::getSessionFromRequest(); $session->doLogin($authId, self::extractPersistentAuthState($state)); SimpleSAML_Utilities::redirectUntrustedURL($redirectTo); } }