/** * Process an authentication response. * * This function saves the state, and if necessary redirects the user to the page where the user * is informed about the expiry date of his/her certificate. * * @param array $state The state of the response. */ public function process(&$state) { assert('is_array($state)'); if (isset($state['isPassive']) && $state['isPassive'] === TRUE) { // We have a passive request. Skip the warning return; } if (!isset($_SERVER['SSL_CLIENT_CERT']) || $_SERVER['SSL_CLIENT_CERT'] == '') { return; } $client_cert = $_SERVER['SSL_CLIENT_CERT']; $client_cert_data = openssl_x509_parse($client_cert); if ($client_cert_data == FALSE) { SimpleSAML\Logger::error('authX509: invalid cert'); return; } $validTo = $client_cert_data['validTo_time_t']; $now = time(); $daysleft = (int) (($validTo - $now) / (24 * 60 * 60)); if ($daysleft > $this->warndaysbefore) { // We have a certificate that will be valid for some time. Skip the warning return; } SimpleSAML\Logger::warning('authX509: user certificate expires in ' . $daysleft . ' days'); $state['daysleft'] = $daysleft; $state['renewurl'] = $this->renewurl; /* Save state and redirect. */ $id = SimpleSAML_Auth_State::saveState($state, 'warning:expire'); $url = SimpleSAML\Module::getModuleURL('authX509/expirywarning.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Log in using an external authentication helper * * @param array &$state Information about the current authentication */ public function authenticate(&$state) { $state['dataportenoauth2:AuthID'] = $this->authId; $state_id = SimpleSAML_Auth_State::saveState($state, 'dataportenoauth2:Connect', TRUE); $info = $this->getConfig($state_id); HTTP::redirectTrustedURL($info['auth'], array("client_id" => $info["client_id"], "redirect_uri" => $info["redirect_uri"], "response_type" => "code", "state" => $state_id)); }
/** * Log in using an external authentication helper. * * @param array &$state Information about the current authentication. */ public function authenticate(&$state) { $state['openidconnect:AuthID'] = $this->authId; $stateId = SimpleSAML_Auth_State::saveState($state, 'openidconnect:Connect', TRUE); $info = $this->getConfig($stateId); \SimpleSAML\Utils\HTTP::redirectTrustedURL($info["client_info"]["authorization_endpoint"], array("client_id" => $info["client_info"]["client_id"], "redirect_uri" => $info["client_info"]["redirect_uri"], "response_type" => "code", "scope" => $this->scope, "state" => $stateId)); }
/** * Constructor for this authentication source. * * @param array $info Information about this authentication source. * @param array $config Configuration. */ public function __construct($info, $config) { assert('is_array($info)'); assert('is_array($config)'); // Call the parent constructor first, as required by the interface parent::__construct($info, $config); // Parse configuration. $config = SimpleSAML_Configuration::loadFromArray($config, 'Authentication source ' . var_export($this->authId, true)); $this->servers = $config->getArray('servers', array()); /* For backwards compatibility. */ if (empty($this->servers)) { $this->hostname = $config->getString('hostname'); $this->port = $config->getIntegerRange('port', 1, 65535, 1812); $this->secret = $config->getString('secret'); $this->servers[] = array('hostname' => $this->hostname, 'port' => $this->port, 'secret' => $this->secret); } $this->timeout = $config->getInteger('timeout', 5); $this->retries = $config->getInteger('retries', 3); $this->realm = $config->getString('realm', null); $this->usernameAttribute = $config->getString('username_attribute', null); $this->nasIdentifier = $config->getString('nas_identifier', \SimpleSAML\Utils\HTTP::getSelfHost()); $this->vendor = $config->getInteger('attribute_vendor', null); if ($this->vendor !== null) { $this->vendorType = $config->getInteger('attribute_vendor_type'); } }
/** * When the process logic determines that the user is not * authorized for this service, then forward the user to * an 403 unauthorized page. * * Separated this code into its own method so that child * classes can override it and change the action. Forward * thinking in case a "chained" ACL is needed, more complex * permission logic. * * @param array $request */ protected function unauthorized(&$request) { SimpleSAML_Logger::error('ExpectedAuthnContextClassRef: Invalid authentication context: ' . $this->AuthnContextClassRef . '. Accepted values are: ' . var_export($this->accepted, true)); $id = SimpleSAML_Auth_State::saveState($request, 'saml:ExpectedAuthnContextClassRef:unauthorized'); $url = SimpleSAML_Module::getModuleURL('saml/sp/wrong_authncontextclassref.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Start the logout operation. * * @param array &$state The logout state. * @param string|null $assocId The SP we are logging out from. */ public function startLogout(array &$state, $assocId) { assert('is_string($assocId) || is_null($assocId)'); $associations = $this->idp->getAssociations(); if (count($associations) === 0) { $this->idp->finishLogout($state); } foreach ($associations as $id => &$association) { $idp = SimpleSAML_IdP::getByState($association); $association['core:Logout-IFrame:Name'] = $idp->getSPName($id); $association['core:Logout-IFrame:State'] = 'onhold'; } $state['core:Logout-IFrame:Associations'] = $associations; if (!is_null($assocId)) { $spName = $this->idp->getSPName($assocId); if ($spName === null) { $spName = array('en' => $assocId); } $state['core:Logout-IFrame:From'] = $spName; } else { $state['core:Logout-IFrame:From'] = null; } $params = array('id' => SimpleSAML_Auth_State::saveState($state, 'core:Logout-IFrame')); if (isset($state['core:Logout-IFrame:InitType'])) { $params['type'] = $state['core:Logout-IFrame:InitType']; } $url = SimpleSAML_Module::getModuleURL('core/idp/logout-iframe.php', $params); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url); }
public function finalStep(&$state) { SimpleSAML_Logger::debug("oauth wrap: Using this verification code [" . $state['authwindowslive:wrap_verification_code'] . "]"); // Retrieve Access Token // Documentation at: http://msdn.microsoft.com/en-us/library/ff749686.aspx $postData = 'wrap_client_id=' . urlencode($this->key) . '&wrap_client_secret=' . urlencode($this->secret) . '&wrap_callback=' . urlencode(SimpleSAML_Module::getModuleUrl('authwindowslive') . '/linkback.php') . '&wrap_verification_code=' . urlencode($state['authwindowslive:wrap_verification_code']); $context = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postData)); $result = \SimpleSAML\Utils\HTTP::fetch('https://consent.live.com/AccessToken.aspx', $context); parse_str($result, $response); // error checking of $response to make sure we can proceed if (!array_key_exists('wrap_access_token', $response)) { throw new Exception('[' . $response['error_code'] . '] ' . $response['wrap_error_reason'] . "\r\nNo wrap_access_token returned - cannot proceed\r\n" . $response['internal_info']); } SimpleSAML_Logger::debug("Got an access token from the OAuth WRAP service provider [" . $response['wrap_access_token'] . "] for user [" . $response['uid'] . "]"); // Documentation at: http://msdn.microsoft.com/en-us/library/ff751708.aspx $opts = array('http' => array('header' => "Accept: application/json\r\nAuthorization: WRAP access_token=" . $response['wrap_access_token'] . "\r\n")); $data = \SimpleSAML\Utils\HTTP::fetch('https://apis.live.net/V4.1/cid-' . $response['uid'] . '/Profiles', $opts); $userdata = json_decode($data, TRUE); $attributes = array(); $attributes['windowslive_uid'] = array($response['uid']); $attributes['windowslive_targetedID'] = array('http://windowslive.com!' . $response['uid']); $attributes['windowslive_user'] = array($response['uid'] . '@windowslive.com'); if (array_key_exists('Entries', $userdata)) { foreach ($userdata['Entries'][0] as $key => $value) { if (is_string($value)) { $attributes['windowslive.' . $key] = array((string) $value); } } if (array_key_exists('Emails', $userdata['Entries'][0])) { $attributes['windowslive_mail'] = array($userdata['Entries'][0]['Emails'][0]['Address']); } } SimpleSAML_Logger::debug('LiveID Returned Attributes: ' . implode(", ", array_keys($attributes))); $state['Attributes'] = $attributes; }
/** * @param $state * * @throws Exception */ public function finalStep(&$state) { SimpleSAML\Logger::debug("authwindowslive oauth: Using this verification code [" . $state['authwindowslive:verification_code'] . "]"); // retrieve Access Token // documentation at: // https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols-oauth-code/#request-an-access-token $postData = 'client_id=' . urlencode($this->key) . '&client_secret=' . urlencode($this->secret) . '&scope=' . urlencode('https://graph.microsoft.com/user.read') . '&grant_type=authorization_code' . '&redirect_uri=' . urlencode(SimpleSAML\Module::getModuleUrl('authwindowslive') . '/linkback.php') . '&code=' . urlencode($state['authwindowslive:verification_code']); $context = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postData)); $result = \SimpleSAML\Utils\HTTP::fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', $context); $response = json_decode($result, true); // error checking of $response to make sure we can proceed if (!array_key_exists('access_token', $response)) { throw new Exception('[' . $response['error'] . '] ' . $response['error_description'] . "\r\nNo access_token returned - cannot proceed\r\n" . implode(', ', $response['error_codes'])); } SimpleSAML\Logger::debug("authwindowslive: Got an access token from the OAuth service provider [" . $response['access_token'] . "]"); // documentation at: http://graph.microsoft.io/en-us/docs/overview/call_api $opts = array('http' => array('header' => "Accept: application/json\r\nAuthorization: Bearer " . $response['access_token'] . "\r\n")); $data = \SimpleSAML\Utils\HTTP::fetch('https://graph.microsoft.com/v1.0/me', $opts); $userdata = json_decode($data, true); // this is the simplest case if (!array_key_exists('@odata.context', $userdata) || array_key_exists('error', $userdata)) { throw new Exception('Unable to retrieve userdata from Microsoft Graph [' . $userdata['error']['code'] . '] ' . $userdata['error']['message']); } $attributes = array(); $attributes['windowslive_targetedID'] = array('https://graph.microsoft.com!' . (!empty($userdata['id']) ? $userdata['id'] : 'unknown')); foreach ($userdata as $key => $value) { if (is_string($value)) { $attributes['windowslive.' . $key] = array((string) $value); } } SimpleSAML\Logger::debug('LiveID Returned Attributes: ' . implode(", ", array_keys($attributes))); $state['Attributes'] = $attributes; }
/** * Process a authentication response. * * This function checks how long it is since the last time the user was authenticated. * If it is to short a while since, we will show a warning to the user. * * @param array $state The state of the response. */ public function process(&$state) { assert('is_array($state)'); if (!array_key_exists('PreviousSSOTimestamp', $state)) { /* * No timestamp from the previous SSO to this SP. This is the first * time during this session. */ return; } $timeDelta = time() - $state['PreviousSSOTimestamp']; if ($timeDelta >= 10) { /* At least 10 seconds since last attempt. */ return; } if (array_key_exists('Destination', $state) && array_key_exists('entityid', $state['Destination'])) { $entityId = $state['Destination']['entityid']; } else { $entityId = 'UNKNOWN'; } SimpleSAML_Logger::warning('WarnShortSSOInterval: Only ' . $timeDelta . ' seconds since last SSO for this user from the SP ' . var_export($entityId, TRUE)); /* Save state and redirect. */ $id = SimpleSAML_Auth_State::saveState($state, 'core:short_sso_interval'); $url = SimpleSAML_Module::getModuleURL('core/short_sso_interval.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Attach the data to the token, and establish the Callback URL and verifier * @param $requestTokenKey RequestToken that was authorized * @param $data Data that is authorized and to be attached to the requestToken * @return array(string:url, string:verifier) ; empty verifier for 1.0-response */ public function authorize($requestTokenKey, $data) { $url = null; $verifier = ''; $version = $this->defaultversion; // See whether to remember values from the original requestToken request: $request_attributes = $this->store->get('requesttorequest', $requestTokenKey, ''); // must be there .. if ($request_attributes['value']) { // establish version to work with $v = $request_attributes['value']['version']; if ($v) { $version = $v; } // establish callback to use if ($request_attributes['value']['callback']) { $url = $request_attributes['value']['callback']; } } // Is there a callback registered? This is leading, even over a supplied oauth_callback-parameter $oConsumer = $this->lookup_consumer($request_attributes['value']['consumerKey']); if ($oConsumer && $oConsumer->callback_url) { $url = $oConsumer->callback_url; } $verifier = SimpleSAML\Utils\Random::generateID(); $url = \SimpleSAML\Utils\HTTP::addURLParameters($url, array("oauth_verifier" => $verifier)); $this->store->set('authorized', $requestTokenKey, $verifier, $data, $this->config->getValue('requestTokenDuration', 60 * 30)); return array($url, $verifier); }
/** * CriticalConfigurationError constructor. * * @param string|null $reason The reason for this critical error. * @param string|null $file The configuration file that originated this error. * @param array|null The configuration array that led to this problem. */ public function __construct($reason = null, $file = null, $config = null) { if ($config === null) { $config = self::$minimum_config; $config['baseurlpath'] = \SimpleSAML\Utils\HTTP::guessBasePath(); } \SimpleSAML_Configuration::loadFromArray($config, '', 'simplesaml'); parent::__construct($reason, $file); }
public function authenticate(&$state) { assert('is_array($state)'); // We are going to need the authId in order to retrieve this authentication source later $state[self::AUTHID] = $this->authId; $id = SimpleSAML_Auth_State::saveState($state, self::STAGEID); $url = SimpleSAML\Module::getModuleURL('InfoCard/login-infocard.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('AuthState' => $id)); }
/** * Retrieve a admin login URL. * * @param string|NULL $returnTo The URL the user should arrive on after admin authentication. Defaults to null. * * @return string A URL which can be used for admin authentication. * @throws \InvalidArgumentException If $returnTo is neither a string nor null. */ public static function getAdminLoginURL($returnTo = null) { if (!(is_string($returnTo) || is_null($returnTo))) { throw new \InvalidArgumentException('Invalid input parameters.'); } if ($returnTo === null) { $returnTo = \SimpleSAML\Utils\HTTP::getSelfURL(); } return \SimpleSAML_Module::getModuleURL('core/login-admin.php', array('ReturnTo' => $returnTo)); }
/** * Initialize processing of the redirect test. * * @param array &$state The state we should update. */ public function process(&$state) { assert('is_array($state)'); assert('array_key_exists("Attributes", $state)'); // To check whether the state is saved correctly $state['Attributes']['RedirectTest1'] = array('OK'); // Save state and redirect $id = SimpleSAML_Auth_State::saveState($state, 'exampleauth:redirectfilter-test'); $url = SimpleSAML_Module::getModuleURL('exampleauth/redirecttest.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Process a authentication response. * * This function saves the state, and redirects the user to the page where the user * can authorize the release of the attributes. * * @param array $state The state of the response. */ public function process(&$state) { assert('is_array($state)'); if (isset($state['isPassive']) && $state['isPassive'] === TRUE) { /* We have a passive request. Skip the warning. */ return; } /* Save state and redirect. */ $id = SimpleSAML_Auth_State::saveState($state, 'warning:request'); $url = SimpleSAML_Module::getModuleURL('preprodwarning/showwarning.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); }
/** * Create a new NotFound error * * @param string $reason Optional description of why the given page could not be found. */ public function __construct($reason = NULL) { assert('is_null($reason) || is_string($reason)'); $url = \SimpleSAML\Utils\HTTP::getSelfURL(); if ($reason === NULL) { parent::__construct(array('NOTFOUND', '%URL%' => $url)); } else { parent::__construct(array('NOTFOUNDREASON', '%URL%' => $url, '%REASON%' => $reason)); } $this->reason = $reason; $this->httpCode = 404; }
function showEntry($t, $metadata, $favourite = FALSE) { $basequerystring = '?' . 'entityID=' . urlencode($t->data['entityID']) . '&' . 'return=' . urlencode($t->data['return']) . '&' . 'returnIDParam=' . urlencode($t->data['returnIDParam']) . '&idpentityid='; $extra = $favourite ? ' favourite' : ''; $html = '<a class="metaentry' . $extra . '" href="' . $basequerystring . urlencode($metadata['entityid']) . '">'; $html .= '' . htmlspecialchars(getTranslatedName($t, $metadata)) . ''; if (array_key_exists('icon', $metadata) && $metadata['icon'] !== NULL) { $iconUrl = \SimpleSAML\Utils\HTTP::resolveURL($metadata['icon']); $html .= '<img alt="Icon for identity provider" class="entryicon" src="' . htmlspecialchars($iconUrl) . '" />'; } $html .= '</a>'; return $html; }
/** * Log-in using Facebook platform * * @param array &$state Information about the current authentication. */ public function authenticate(&$state) { assert('is_array($state)'); /* We are going to need the authId in order to retrieve this authentication source later. */ $state[self::AUTHID] = $this->authId; $stateID = SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT); $facebook = new sspmod_authfacebook_Facebook(array('appId' => $this->api_key, 'secret' => $this->secret), $state); $facebook->destroySession(); $linkback = SimpleSAML_Module::getModuleURL('authfacebook/linkback.php', array('AuthState' => $stateID)); $url = $facebook->getLoginUrl(array('redirect_uri' => $linkback, 'scope' => $this->req_perms)); SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT); \SimpleSAML\Utils\HTTP::redirectTrustedURL($url); }
/** * Test SimpleSAML\Utils\HTTP::getSelfHostWithPort(), with and without custom port. */ public function testGetSelfHostWithPort() { \SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => ''), '[ARRAY]', 'simplesaml'); // standard port for HTTP $_SERVER['SERVER_PORT'] = '80'; $this->assertEquals('localhost', HTTP::getSelfHostWithNonStandardPort()); // non-standard port $_SERVER['SERVER_PORT'] = '3030'; $this->assertEquals('localhost:3030', HTTP::getSelfHostWithNonStandardPort()); // standard port for HTTPS $_SERVER['HTTPS'] = 'on'; $_SERVER['SERVER_PORT'] = '443'; $this->assertEquals('localhost', HTTP::getSelfHostWithNonStandardPort()); }
/** * Create a new NotFound error * * @param string $reason Optional description of why the given page could not be found. */ public function __construct($reason = NULL) { assert('is_null($reason) || is_string($reason)'); $url = \SimpleSAML\Utils\HTTP::getSelfURL(); if ($reason === NULL) { parent::__construct(array('NOTFOUND', '%URL%' => $url)); $this->message = "The requested page '{$url}' could not be found."; } else { parent::__construct(array('NOTFOUNDREASON', '%URL%' => $url, '%REASON%' => $reason)); $this->message = "The requested page '{$url}' could not be found. " . $reason; } $this->reason = $reason; $this->httpCode = 404; }
/** * The inner workings of the module. Check client's subnet and redirect * to an authentication page protected with "HTTP Negotiate" authentication * or a fallback authentication source. * * @param array &$state Information about the current authentication. */ public function authenticate(&$state) { assert('is_array($state)'); $state['negotiateserver:AuthID'] = $this->authId; $state['negotiateserver:AuthFallback'] = $this->auth_fallback; if (!$this->checkClientSubnet()) { $this->fallback($state); } $stateId = SimpleSAML_Auth_State::saveState($state, 'negotiateserver:Negotiate'); $returnTo = SimpleSAML\Module::getModuleURL('negotiateserver/resume.php', array('State' => $stateId)); $authPage = SimpleSAML\Module::getModuleURL('negotiateserver/preauth.php'); \SimpleSAML\Utils\HTTP::redirectTrustedURL($authPage, array('State' => $stateId, 'ReturnTo' => $returnTo)); assert('FALSE'); }
/** * Retrieve the session id of saved in the session cookie. * * @return string The session id saved in the cookie. */ public function getCookieSessionId() { if (session_id() === '') { if (!self::hasSessionCookie()) { return self::newSessionId(); } $session_cookie_params = session_get_cookie_params(); if ($session_cookie_params['secure'] && !\SimpleSAML\Utils\HTTP::isHTTPS()) { throw new SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.'); } session_start(); } return session_id(); }
/** * Gets the language navigation bar. * * @param SimpleSAML_XHTML_Template $view The view object, * @param array $post The _POST array. * * @return string Resulting html markup. */ function simplesamlphp_get_languagebar(SimpleSAML_XHTML_Template $view, $params = array()) { if (!empty($params['post'])) { return ''; } if (isset($view->data['hideLanguageBar']) && $view->data['hideLanguageBar'] === TRUE) { return ''; } $languages = simplesamlphp_get_languages(); $result = '<ul class="dropdown-menu">'; $template = '<li><a href="!href">!name</a></li>'; foreach ($languages as $lang => $name) { $href = \SimpleSAML\Utils\HTTP::addURLParameters(\SimpleSAML\Utils\HTTP::getSelfURL(), array($params['languageParameterName'] => $lang)); $result .= strtr($template, array('!href' => $href, '!name' => $name)); } return $result . '</ul>'; }
/** * Send an authenticationResponse using HTTP-POST. * * @param string $response The response which should be sent. * @param SimpleSAML_Configuration $idpmd The metadata of the IdP which is sending the response. * @param SimpleSAML_Configuration $spmd The metadata of the SP which is receiving the response. * @param string|null $relayState The relaystate for the SP. * @param string $shire The shire which should receive the response. */ public function sendResponse($response, SimpleSAML_Configuration $idpmd, SimpleSAML_Configuration $spmd, $relayState, $shire) { \SimpleSAML\Utils\XML::checkSAMLMessage($response, 'saml11'); $privatekey = SimpleSAML\Utils\Crypto::loadPrivateKey($idpmd, true); $publickey = SimpleSAML\Utils\Crypto::loadPublicKey($idpmd, true); $responsedom = new DOMDocument(); $responsedom->loadXML(str_replace("\r", "", $response)); $responseroot = $responsedom->getElementsByTagName('Response')->item(0); $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0); /* Determine what we should sign - either the Response element or the Assertion. The default is to sign the * Assertion, but that can be overridden by the 'signresponse' option in the SP metadata or * 'saml20.signresponse' in the global configuration. * * TODO: neither 'signresponse' nor 'shib13.signresponse' are valid options any longer. Remove! */ if ($spmd->hasValue('signresponse')) { $signResponse = $spmd->getBoolean('signresponse'); } else { $signResponse = $this->configuration->getBoolean('shib13.signresponse', true); } // check if we have an assertion to sign. Force to sign the response if not if ($firstassertionroot === null) { $signResponse = true; } $signer = new SimpleSAML_XML_Signer(array('privatekey_array' => $privatekey, 'publickey_array' => $publickey, 'id' => $signResponse ? 'ResponseID' : 'AssertionID')); if ($idpmd->hasValue('certificatechain')) { $signer->addCertificate($idpmd->getString('certificatechain')); } if ($signResponse) { // sign the response - this must be done after encrypting the assertion // we insert the signature before the saml2p:Status element $statusElements = SimpleSAML\Utils\XML::getDOMChildren($responseroot, 'Status', '@saml1p'); assert('count($statusElements) === 1'); $signer->sign($responseroot, $responseroot, $statusElements[0]); } else { /* Sign the assertion */ $signer->sign($firstassertionroot, $firstassertionroot); } $response = $responsedom->saveXML(); \SimpleSAML\Utils\XML::debugSAMLMessage($response, 'out'); \SimpleSAML\Utils\HTTP::submitPOSTData($shire, array('TARGET' => $relayState, 'SAMLResponse' => base64_encode($response))); }
/** * Log-in using Twitter platform * * @param array &$state Information about the current authentication. */ public function authenticate(&$state) { assert('is_array($state)'); /* We are going to need the authId in order to retrieve this authentication source later. */ $state[self::AUTHID] = $this->authId; $stateID = SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT); $consumer = new sspmod_oauth_Consumer($this->key, $this->secret); // Get the request token $linkback = SimpleSAML_Module::getModuleURL('authtwitter/linkback.php', array('AuthState' => $stateID)); $requestToken = $consumer->getRequestToken('https://api.twitter.com/oauth/request_token', array('oauth_callback' => $linkback)); SimpleSAML_Logger::debug("Got a request token from the OAuth service provider [" . $requestToken->key . "] with the secret [" . $requestToken->secret . "]"); $state['authtwitter:authdata:requestToken'] = $requestToken; SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT); // Authorize the request token $url = 'https://api.twitter.com/oauth/authenticate'; if ($this->force_login) { $url = \SimpleSAML\Utils\HTTP::addURLParameters($url, array('force_login' => 'true')); } $consumer->getAuthorizeRequest($url, $requestToken); }
/** * Picks the next SP and issues a logout request. * * This function never returns. * * @param array &$state The logout state. */ private function logoutNextSP(array &$state) { $association = array_pop($state['core:LogoutTraditional:Remaining']); if ($association === null) { $this->idp->finishLogout($state); } $relayState = \SimpleSAML_Auth_State::saveState($state, 'core:LogoutTraditional', true); $id = $association['id']; Logger::info('Logging out of ' . var_export($id, true) . '.'); try { $idp = \SimpleSAML_IdP::getByState($association); $url = call_user_func(array($association['Handler'], 'getLogoutURL'), $idp, $association, $relayState); HTTP::redirectTrustedURL($url); } catch (\Exception $e) { Logger::warning('Unable to initialize logout to ' . var_export($id, true) . '.'); $this->idp->terminateAssociation($id); $state['core:Failed'] = true; // Try the next SP $this->logoutNextSP($state); assert('FALSE'); } }
/** * @param string $url * @param array $parameters * @return string */ public static function addQueryParametersToUrl($url, array $parameters) { if (count($parameters) > 0) { $fragmentStart = strpos($url, '#'); if ($fragmentStart !== false) { //strip fragment if any $fragment = substr($url, $fragmentStart); $url = substr($url, 0, $fragmentStart); } else { $fragment = ''; } $queryStart = strpos($url, '?'); if ($queryStart !== false) { //strip query if any $query = \SimpleSAML\Utils\HTTP::parseQueryString(substr($url, $queryStart + 1)); $url = substr($url, 0, $queryStart); } else { $query = array(); } $query = array_merge($query, $parameters); $url .= '?' . http_build_query($query, '', '&') . $fragment; } return $url; }
/** * Test SimpleSAML\Utils\HTTP::checkURLAllowed(), with the regex as a * subdomain of an evil domain. */ public function testCheckURLAllowedWithRegexWithoutDelimiters() { $original = $_SERVER; \SimpleSAML_Configuration::loadFromArray(array('trusted.url.domains' => array('app\\.example\\.com'), 'trusted.url.regex' => true), '[ARRAY]', 'simplesaml'); $_SERVER['REQUEST_URI'] = '/module.php'; $this->setExpectedException('SimpleSAML_Error_Exception'); HTTP::checkURLAllowed('https://app.example.com.evil.com'); $_SERVER = $original; }
<?php /** * This SAML 2.0 endpoint can receive incoming LogoutRequests. It will also send LogoutResponses, * and LogoutRequests and also receive LogoutResponses. It is implemeting SLO at the SAML 2.0 IdP. * * @author Andreas Åkre Solberg, UNINETT AS. <*****@*****.**> * @package SimpleSAMLphp */ require_once '../../_include.php'; SimpleSAML\Logger::info('SAML2.0 - IdP.SingleLogoutService: Accessing SAML 2.0 IdP endpoint SingleLogoutService'); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); $idp = SimpleSAML_IdP::getById('saml2:' . $idpEntityId); if (isset($_REQUEST['ReturnTo'])) { $idp->doLogoutRedirect(\SimpleSAML\Utils\HTTP::checkURLAllowed((string) $_REQUEST['ReturnTo'])); } else { try { sspmod_saml_IdP_SAML2::receiveLogoutMessage($idp); } catch (Exception $e) { // TODO: look for a specific exception /* * This is dirty. Instead of checking the message of the exception, \SAML2\Binding::getCurrentBinding() should * throw an specific exception when the binding is unknown, and we should capture that here */ if ($e->getMessage() === 'Unable to find the current binding.') { throw new SimpleSAML_Error_Error('SLOSERVICEPARAMS', $e, 400); } else { throw $e; // do not ignore other exceptions! }
/** * Set the previous authentication source. * * This method remembers the authentication source that the user selected * by storing its name in a cookie. * * @param string $source Name of the authentication source the user selected. */ public function setPreviousSource($source) { assert('is_string($source)'); $cookieName = 'multiauth_source_' . $this->authId; $config = SimpleSAML_Configuration::getInstance(); $params = array('lifetime' => 60 * 60 * 24 * 90, 'path' => $config->getBasePath(), 'httponly' => FALSE); \SimpleSAML\Utils\HTTP::setCookie($cookieName, $source, $params, FALSE); }