1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
|
<?php
/**
* Implements the default behaviour for authentication.
*
* This class contains an implementation for default behaviour when authenticating. It will
* save the session information it got from the authentication client in the users session.
*
* @author Olav Morken, UNINETT AS.
* @package simpleSAMLphp
*/
class SimpleSAML_Auth_Default {
/**
* Start authentication.
*
* This function never returns.
*
* @param string $authId The identifier of the authentication source.
* @param string|array $return The URL or function we should direct the
* user to after authentication. If using a URL obtained from user input,
* please make sure to check it by calling
* SimpleSAML_Utilities::checkURLAllowed().
* @param string|NULL $errorURL The URL we should direct the user to after
* failed authentication. Can be NULL, in which case a standard error page
* will be shown. If using a URL obtained from user input, please make sure
* to check it by calling SimpleSAML_Utilities::checkURLAllowed().
* @param array $params Extra information about the login. Different
* authentication requestors may provide different information. Optional,
* will default to an empty array.
*/
public static function initLogin($authId, $return, $errorURL = NULL,
array $params = array()) {
assert('is_string($authId)');
assert('is_string($return) || is_array($return)');
assert('is_string($errorURL) || is_null($errorURL)');
$state = array_merge($params, array(
'SimpleSAML_Auth_Default.id' => $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);
}
}
|