41 assert(is_array(
$info));
47 if (!isset(
$config[
'entityID'])) {
56 'authsources[' . var_export($this->authId,
true) .
']');
57 $this->entityId = $this->metadata->getString(
'entityID');
58 $this->idp = $this->metadata->getString(
'idp', null);
59 $this->discoURL = $this->metadata->getString(
'discoURL', null);
61 if (empty($this->discoURL) &&
SimpleSAML\Module::isModuleEnabled(
'discojuice')) {
106 if ($this->idp !== null && $this->idp !==
$entityId) {
109 ' because it isn\'t a valid IdP for this SP.');
116 return $metadataHandler->getMetaDataConfig(
$entityId,
'saml20-idp-remote');
124 return $metadataHandler->getMetaDataConfig(
$entityId,
'shib13-idp-remote');
147 $ar = new \SimpleSAML\XML\Shib13\AuthnRequest();
148 $ar->setIssuer($this->entityId);
151 $ar->setRelayState(
$id);
153 $useArtifact = $idpMetadata->
getBoolean(
'saml1.useartifact', null);
154 if ($useArtifact === null) {
155 $useArtifact = $this->metadata->getBoolean(
'saml1.useartifact',
false);
167 ' from ' . var_export($this->entityId,
true) .
'.');
179 if (isset($state[
'saml:ProxyCount']) && $state[
'saml:ProxyCount'] < 0) {
182 new \
SimpleSAML\Module\saml\Error\ProxyCountExceeded(\
SAML2\Constants::STATUS_RESPONDER)
192 $ar->setAssertionConsumerServiceURL(ILIAS_HTTP_PATH .
'/Services/Saml/lib/saml2-acs.php/default-sp/' . CLIENT_ID);
195 if (isset($state[
'SimpleSAML_Auth_Source.ReturnURL'])) {
196 $ar->setRelayState($state[
'SimpleSAML_Auth_Source.ReturnURL']);
199 if (isset($state[
'saml:AuthnContextClassRef'])) {
202 if (isset($state[
'saml:AuthnContextComparison']) && in_array($state[
'AuthnContextComparison'], array(
203 SAML2\Constants::COMPARISON_EXACT,
204 SAML2\Constants::COMPARISON_MINIMUM,
205 SAML2\Constants::COMPARISON_MAXIMUM,
206 SAML2\Constants::COMPARISON_BETTER,
208 $comp = $state[
'saml:AuthnContextComparison'];
210 $ar->setRequestedAuthnContext(array(
'AuthnContextClassRef' => $accr,
'Comparison' => $comp));
213 if (isset($state[
'ForceAuthn'])) {
214 $ar->setForceAuthn((
bool)$state[
'ForceAuthn']);
217 if (isset($state[
'isPassive'])) {
218 $ar->setIsPassive((
bool)$state[
'isPassive']);
221 if (isset($state[
'saml:NameID'])) {
222 if (!is_array($state[
'saml:NameID']) && !is_a($state[
'saml:NameID'],
'\SAML2\XML\saml\NameID')) {
225 $ar->setNameId($state[
'saml:NameID']);
228 if (isset($state[
'saml:NameIDPolicy'])) {
229 if (is_string($state[
'saml:NameIDPolicy'])) {
231 'Format' => (
string)$state[
'saml:NameIDPolicy'],
232 'AllowCreate' =>
true,
234 } elseif (is_array($state[
'saml:NameIDPolicy'])) {
235 $policy = $state[
'saml:NameIDPolicy'];
239 $ar->setNameIdPolicy($policy);
242 if (isset($state[
'saml:IDPList'])) {
243 $IDPList = $state[
'saml:IDPList'];
248 $ar->setIDPList(array_unique(array_merge($this->metadata->getArray(
'IDPList', array()),
249 $idpMetadata->
getArray(
'IDPList', array()),
252 if (isset($state[
'saml:ProxyCount']) && $state[
'saml:ProxyCount'] !== null) {
253 $ar->setProxyCount($state[
'saml:ProxyCount']);
254 } elseif ($idpMetadata->
getInteger(
'ProxyCount', null) !== null) {
255 $ar->setProxyCount($idpMetadata->
getInteger(
'ProxyCount', null));
256 } elseif ($this->metadata->getInteger(
'ProxyCount', null) !== null) {
257 $ar->setProxyCount($this->metadata->getInteger(
'ProxyCount', null));
260 $requesterID = array();
261 if (isset($state[
'saml:RequesterID'])) {
262 $requesterID = $state[
'saml:RequesterID'];
265 if (isset($state[
'core:SP'])) {
266 $requesterID[] = $state[
'core:SP'];
269 $ar->setRequesterID($requesterID);
271 if (isset($state[
'saml:Extensions'])) {
272 $ar->setExtensions($state[
'saml:Extensions']);
276 $state[
'ExpectedIssuer'] = $idpMetadata->
getString(
'entityid');
282 var_export($idpMetadata->
getString(
'entityid'),
true));
287 \
SAML2\Constants::BINDING_HOK_SSO)
291 \
SAML2\Constants::BINDING_HTTP_REDIRECT,
292 \
SAML2\Constants::BINDING_HTTP_POST,
295 $ar->setDestination(
$dst[
'Location']);
327 assert(is_string(
$idp));
333 case 'shib13-idp-remote':
336 case 'saml20-idp-remote':
363 'entityID' => $this->entityId,
365 'returnIDParam' =>
'idpentityid' 368 if(isset($state[
'saml:IDPList'])) {
369 $params[
'IDPList'] = $state[
'saml:IDPList'];
372 if (isset($state[
'isPassive']) && $state[
'isPassive']) {
395 if (isset(
$state[
'saml:idp'])) {
399 if (isset(
$state[
'saml:IDPList']) &&
sizeof(
$state[
'saml:IDPList']) > 0) {
402 $known_idps =
$mdh->getList();
403 $intersection = array_intersect(
$state[
'saml:IDPList'], array_keys($known_idps));
405 if (empty($intersection)) {
408 \
SAML2\Constants::STATUS_REQUESTER,
409 'None of the IdPs requested are supported by this proxy.' 413 if (!is_null(
$idp) && !in_array(
$idp, $intersection,
true)) {
416 \
SAML2\Constants::STATUS_REQUESTER,
417 'None of the IdPs requested are available to this proxy.' 421 if (is_null(
$idp) &&
sizeof($intersection) === 1) {
446 assert(is_array($state));
450 foreach (
$data as $k => $v) {
455 if (isset($state[
'saml:IDPList']) &&
sizeof($state[
'saml:IDPList']) > 0 &&
456 !in_array($state[
'saml:sp:IdP'], $state[
'saml:IDPList'],
true))
467 $known_idps =
$mdh->getList();
468 $intersection = array_intersect($state[
'saml:IDPList'], array_keys($known_idps));
470 if (empty($intersection)) {
473 \
SAML2\Constants::STATUS_REQUESTER,
474 'None of the IdPs requested are supported by this proxy.' 483 if (!is_null($this->idp) && !in_array($this->idp, $intersection,
true)) {
486 \
SAML2\Constants::STATUS_REQUESTER,
487 'None of the IdPs requested are available to this proxy.' 497 "Reauthentication after logout is needed. The IdP '${state['saml:sp:IdP']}' is not in the IDPList ".
498 "provided by the Service Provider '${state['core:SP']}'." 501 $state[
'saml:sp:IdPMetadata'] = $this->
getIdPMetadata($state[
'saml:sp:IdP']);
503 self::askForIdPChange($state);
529 assert(array_key_exists(
'saml:sp:IdPMetadata', $state));
530 assert(array_key_exists(
'saml:sp:AuthId', $state));
531 assert(array_key_exists(
'core:IdP', $state));
532 assert(array_key_exists(
'SPMetadata', $state));
534 if (isset($state[
'isPassive']) && (
bool)$state[
'isPassive']) {
537 \
SAML2\Constants::STATUS_REQUESTER,
538 'Reauthentication required' 560 if (isset($state[
'Responder'])) {
561 $state[
'saml:proxy:reauthLogout:PrevResponder'] = $state[
'Responder'];
563 $state[
'Responder'] = array(
'sspmod_saml_Auth_Source_SP',
'reauthPostLogout');
566 $idp->handleLogoutRequest($state, null);
577 assert(isset($state[
'ReturnCallback']));
581 $authId = $state[
'saml:sp:AuthId'];
585 call_user_func($state[
'ReturnCallback'], $state);
599 assert(isset($state[
'saml:sp:AuthId']));
603 if (isset($state[
'saml:proxy:reauthLogout:PrevResponder'])) {
604 $state[
'Responder'] = $state[
'saml:proxy:reauthLogout:PrevResponder'];
610 $sp->authenticate($state);
621 assert(is_array($state));
622 assert(array_key_exists(
'saml:logout:IdP', $state));
623 assert(array_key_exists(
'saml:logout:NameID', $state));
624 assert(array_key_exists(
'saml:logout:SessionIndex', $state));
628 $idp = $state[
'saml:logout:IdP'];
629 $nameId = $state[
'saml:logout:NameID'];
635 \
SAML2\Constants::BINDING_HTTP_REDIRECT,
636 \
SAML2\Constants::BINDING_HTTP_POST),
false);
650 $encryptNameId = $this->metadata->getBoolean(
'nameid.encryption',
false);
669 assert(is_array($state));
670 assert(array_key_exists(
'saml:logout:Type', $state));
672 $logoutType = $state[
'saml:logout:Type'];
673 switch ($logoutType) {
695 assert(is_string($idp));
696 assert(array_key_exists(
'LogoutState', $state));
697 assert(array_key_exists(
'saml:logout:Type', $state[
'LogoutState']));
701 $spMetadataArray = $this->metadata->toArray();
705 $state[
'saml:sp:IdP'] =
$idp;
706 $state[
'PersistentAuthData'][] =
'saml:sp:IdP';
708 $authProcState = array(
709 'saml:sp:IdP' => $idp,
710 'saml:sp:State' => $state,
711 'ReturnCall' => array(
'sspmod_saml_Auth_Source_SP',
'onProcessingCompleted'),
713 'Attributes' => $attributes,
714 'Destination' => $spMetadataArray,
715 'Source' => $idpMetadataArray,
718 if (isset($state[
'saml:sp:NameID'])) {
719 $authProcState[
'saml:sp:NameID'] = $state[
'saml:sp:NameID'];
721 if (isset($state[
'saml:sp:SessionIndex'])) {
722 $authProcState[
'saml:sp:SessionIndex'] = $state[
'saml:sp:SessionIndex'];
726 $pc->processState($authProcState);
728 self::onProcessingCompleted($authProcState);
761 assert(is_string($redirectTo));
776 assert(array_key_exists(
'saml:sp:IdP', $authProcState));
777 assert(array_key_exists(
'saml:sp:State', $authProcState));
778 assert(array_key_exists(
'Attributes', $authProcState));
780 $idp = $authProcState[
'saml:sp:IdP'];
781 $state = $authProcState[
'saml:sp:State'];
790 $source->addLogoutCallback($idp, $state);
792 $state[
'Attributes'] = $authProcState[
'Attributes'];
794 if (isset($state[
'saml:sp:isUnsolicited']) && (
bool)$state[
'saml:sp:isUnsolicited']) {
795 if (!empty($state[
'saml:sp:RelayState'])) {
796 $redirectTo = $state[
'saml:sp:RelayState'];
798 $redirectTo =
$source->getMetadata()->getString(
'RelayState',
'/');
800 self::handleUnsolicitedAuth(
$sourceId, $state, $redirectTo);
const BINDING_HOK_SSO
The URN for the Holder-of-Key Web Browser SSO Profile binding.
startDisco(array $state)
Start an IdP discovery service operation.
static askForIdPChange(array &$state)
Ask the user to log out before being able to log in again with a different identity provider...
if(!isset($_REQUEST['ReturnTo'])) $returnTo
static getByState(array &$state)
Retrieve the IdP "owning" the state.
getArray($name, $default=self::REQUIRED_OPTION)
This function retrieves an array configuration option.
static arrayize($data, $index=0)
Put a non-array variable into an array.
callLogoutCallback($assoc)
Call a logout callback based on association.
static throwException($state, SimpleSAML_Error_Exception $exception)
Throw exception to the state exception handler.
static getBinding($urn)
Retrieve a binding with the given URN.
getEntityId()
Retrieve the entity id of this SP.
if(!array_key_exists('StateId', $_REQUEST)) $id
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
static reauthPostLogin(array $state)
Complete login operation after re-authenticating the user on another IdP.
static buildLogoutRequest(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata)
Build a logout request based on information in the metadata.
static buildAuthnRequest(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata)
Build an authentication request based on information in the metadata.
static reauthLogout(array $state)
Log the user out before logging in again.
getMetadataURL()
Retrieve the URL to the metadata of this SP.
static redirectUntrustedURL($url, $parameters=array())
This function redirects to the specified URL after performing the appropriate security checks on it...
reauthenticate(array &$state)
Re-authenticate an user.
static getModuleURL($resource, array $parameters=array())
Get absolute URL to a specified module resource.
authenticate(&$state)
Start login.
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Attribute-related utility methods.
if(!array_key_exists(sspmod_authfacebook_Auth_Source_Facebook::AUTHID, $state)) $sourceId
getEndpointPrioritizedByBinding($endpointType, array $bindings, $default=self::REQUIRED_OPTION)
Find an endpoint of the given type, using a list of supported bindings as a way to prioritize...
static onProcessingCompleted(array $authProcState)
Called when we have completed the procssing chain.
logout(&$state)
Start logout operation.
getDefaultEndpoint($endpointType, array $bindings=null, $default=self::REQUIRED_OPTION)
Find the default endpoint of the given type.
const COMPARISON_EXACT
Request Authentication Context Comparison indicating that the resulting authentication context in the...
__construct($info, $config)
Constructor for SAML SP authentication source.
startSSO($idp, array $state)
Send a SSO request to an IdP.
sendSAML2AuthnRequest(array &$state, \SAML2\Binding $binding, \SAML2\AuthnRequest $ar)
Function to actually send the authentication request.
getIdPMetadata($entityId)
Retrieve the metadata of an IdP.
handleResponse(array $state, $idp, array $attributes)
Handle a response from a SSO operation.
getBoolean($name, $default=self::REQUIRED_OPTION)
This function retrieves a boolean configuration option.
if(array_key_exists('yes', $_REQUEST)) $attributes
startSLO2(&$state)
Start a SAML 2 logout operation.
getInteger($name, $default=self::REQUIRED_OPTION)
This function retrieves an integer configuration option.
static getEncryptionKey(SimpleSAML_Configuration $metadata)
Retrieve the encryption key for the given entity.
getMetadata()
Retrieve the metadata of this SP.
static getPersistentAuthData(array $state)
Get the persistent authentication state from the state array.
static handleUnsolicitedAuth($authId, array $state, $redirectTo)
Handle an unsolicited login operations.
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
static completeAuth(&$state)
Complete authentication.
handleLogout($idpEntityId)
Handle a logout request from an IdP.
static getById($authId, $type=null)
Retrieve authentication source.
startSSO2(SimpleSAML_Configuration $idpMetadata, array $state)
Send a SAML2 SSO request to an IdP.
static getSessionFromRequest()
Retrieves the current session.
static loadFromArray($config, $location='[ARRAY]', $instance=null)
Loads a configuration from the given array.
static saveState(&$state, $stage, $rawId=false)
Save the state.
startSSO1(SimpleSAML_Configuration $idpMetadata, array $state)
Send a SAML1 SSO request to an IdP.