ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
sspmod_saml_IdP_SAML2 Class Reference
+ Collaboration diagram for sspmod_saml_IdP_SAML2:

Static Public Member Functions

static sendResponse (array $state)
 Send a response to the SP. More...
 
static handleAuthError (SimpleSAML_Error_Exception $exception, array $state)
 Handle authentication error. More...
 
static receiveAuthnRequest (SimpleSAML_IdP $idp)
 Receive an authentication request. More...
 
static processSOAPAuthnRequest (array &$state)
 
static sendLogoutRequest (SimpleSAML_IdP $idp, array $association, $relayState)
 Send a logout request to a given association. More...
 
static sendLogoutResponse (SimpleSAML_IdP $idp, array $state)
 Send a logout response. More...
 
static receiveLogoutMessage (SimpleSAML_IdP $idp)
 Receive a logout message. More...
 
static getLogoutURL (SimpleSAML_IdP $idp, array $association, $relayState)
 Retrieve a logout URL for a given logout association. More...
 
static getAssociationConfig (SimpleSAML_IdP $idp, array $association)
 Retrieve the metadata for the given SP association. More...
 

Static Private Member Functions

static getAssertionConsumerService (array $supportedBindings, SimpleSAML_Configuration $spMetadata, $AssertionConsumerServiceURL, $ProtocolBinding, $AssertionConsumerServiceIndex)
 Find SP AssertionConsumerService based on parameter in AuthnRequest. More...
 
static generateNameIdValue (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, array &$state)
 Calculate the NameID value that should be used. More...
 
static encodeAttributes (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, array $attributes)
 Helper function for encoding attributes. More...
 
static getAttributeNameFormat (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata)
 Determine which NameFormat we should use for attributes. More...
 
static buildAssertion (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, array &$state)
 Build an assertion based on information in the metadata. More...
 
static encryptAssertion (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, \SAML2\Assertion $assertion)
 Encrypt an assertion. More...
 
static buildLogoutRequest (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, array $association, $relayState)
 Build a logout request based on information in the metadata. More...
 
static buildResponse (SimpleSAML_Configuration $idpMetadata, SimpleSAML_Configuration $spMetadata, $consumerURL)
 Build a authentication response based on information in the metadata. More...
 

Detailed Description

Definition at line 11 of file SAML2.php.

Member Function Documentation

◆ buildAssertion()

static sspmod_saml_IdP_SAML2::buildAssertion ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata,
array &  $state 
)
staticprivate

Build an assertion based on information in the metadata.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
array&$stateThe state array with information about the request.
Returns
The assertion.
Exceptions
SimpleSAML_Error_ExceptionIn case an error occurs when creating a holder-of-key assertion.

Definition at line 865 of file SAML2.php.

References $_SERVER, $assertionLifetime, $attributeNameFormat, $attributes, $config, $encryptNameId, $nameId, $nameIdFormat, $nameIdValue, $sc, sspmod_saml_Message\addSign(), SAML2\Constants\CM_BEARER, SAML2\Constants\CM_HOK, SimpleSAML\Utils\Random\generateID(), SimpleSAML_Configuration\getBoolean(), sspmod_saml_Message\getEncryptionKey(), SimpleSAML_Configuration\getInstance(), SimpleSAML_Configuration\getInteger(), SimpleSAML_Configuration\getString(), SAML2\Constants\NAMEID_TRANSIENT, SubjectConfirmationData, and SimpleSAML\Logger\warning().

869  {
870  assert(isset($state['Attributes']));
871  assert(isset($state['saml:ConsumerURL']));
872 
873  $now = time();
874 
875  $signAssertion = $spMetadata->getBoolean('saml20.sign.assertion', null);
876  if ($signAssertion === null) {
877  $signAssertion = $idpMetadata->getBoolean('saml20.sign.assertion', true);
878  }
879 
881 
882  $a = new \SAML2\Assertion();
883  if ($signAssertion) {
884  sspmod_saml_Message::addSign($idpMetadata, $spMetadata, $a);
885  }
886 
887  $a->setIssuer($idpMetadata->getString('entityid'));
888  $a->setValidAudiences(array($spMetadata->getString('entityid')));
889 
890  $a->setNotBefore($now - 30);
891 
892  $assertionLifetime = $spMetadata->getInteger('assertion.lifetime', null);
893  if ($assertionLifetime === null) {
894  $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300);
895  }
896  $a->setNotOnOrAfter($now + $assertionLifetime);
897 
898  if (isset($state['saml:AuthnContextClassRef'])) {
899  $a->setAuthnContextClassRef($state['saml:AuthnContextClassRef']);
900  } elseif (\SimpleSAML\Utils\HTTP::isHTTPS()) {
901  $a->setAuthnContextClassRef(\SAML2\Constants::AC_PASSWORD_PROTECTED_TRANSPORT);
902  } else {
903  $a->setAuthnContext(\SAML2\Constants::AC_PASSWORD);
904  }
905 
906  $sessionStart = $now;
907  if (isset($state['AuthnInstant'])) {
908  $a->setAuthnInstant($state['AuthnInstant']);
909  $sessionStart = $state['AuthnInstant'];
910  }
911 
912  $sessionLifetime = $config->getInteger('session.duration', 8 * 60 * 60);
913  $a->setSessionNotOnOrAfter($sessionStart + $sessionLifetime);
914 
915  $a->setSessionIndex(SimpleSAML\Utils\Random::generateID());
916 
917  $sc = new \SAML2\XML\saml\SubjectConfirmation();
918  $sc->SubjectConfirmationData = new \SAML2\XML\saml\SubjectConfirmationData();
919  $sc->SubjectConfirmationData->NotOnOrAfter = $now + $assertionLifetime;
920  $sc->SubjectConfirmationData->Recipient = $state['saml:ConsumerURL'];
921  $sc->SubjectConfirmationData->InResponseTo = $state['saml:RequestId'];
922 
923  // ProtcolBinding of SP's <AuthnRequest> overwrites IdP hosted metadata configuration
924  $hokAssertion = null;
925  if ($state['saml:Binding'] === \SAML2\Constants::BINDING_HOK_SSO) {
926  $hokAssertion = true;
927  }
928  if ($hokAssertion === null) {
929  $hokAssertion = $idpMetadata->getBoolean('saml20.hok.assertion', false);
930  }
931 
932  if ($hokAssertion) {
933  // Holder-of-Key
934  $sc->Method = \SAML2\Constants::CM_HOK;
935  if (\SimpleSAML\Utils\HTTP::isHTTPS()) {
936  if (isset($_SERVER['SSL_CLIENT_CERT']) && !empty($_SERVER['SSL_CLIENT_CERT'])) {
937  // extract certificate data (if this is a certificate)
938  $clientCert = $_SERVER['SSL_CLIENT_CERT'];
939  $pattern = '/^-----BEGIN CERTIFICATE-----([^-]*)^-----END CERTIFICATE-----/m';
940  if (preg_match($pattern, $clientCert, $matches)) {
941  // we have a client certificate from the browser which we add to the HoK assertion
942  $x509Certificate = new \SAML2\XML\ds\X509Certificate();
943  $x509Certificate->certificate = str_replace(array("\r", "\n", " "), '', $matches[1]);
944 
945  $x509Data = new \SAML2\XML\ds\X509Data();
946  $x509Data->data[] = $x509Certificate;
947 
948  $keyInfo = new \SAML2\XML\ds\KeyInfo();
949  $keyInfo->info[] = $x509Data;
950 
951  $sc->SubjectConfirmationData->info[] = $keyInfo;
952  } else {
953  throw new SimpleSAML_Error_Exception(
954  'Error creating HoK assertion: No valid client certificate provided during TLS handshake '.
955  'with IdP'
956  );
957  }
958  } else {
959  throw new SimpleSAML_Error_Exception(
960  'Error creating HoK assertion: No client certificate provided during TLS handshake with IdP'
961  );
962  }
963  } else {
964  throw new SimpleSAML_Error_Exception(
965  'Error creating HoK assertion: No HTTPS connection to IdP, but required for Holder-of-Key SSO'
966  );
967  }
968  } else {
969  // Bearer
971  }
972  $a->setSubjectConfirmation(array($sc));
973 
974  // add attributes
975  if ($spMetadata->getBoolean('simplesaml.attributes', true)) {
976  $attributeNameFormat = self::getAttributeNameFormat($idpMetadata, $spMetadata);
977  $a->setAttributeNameFormat($attributeNameFormat);
978  $attributes = self::encodeAttributes($idpMetadata, $spMetadata, $state['Attributes']);
979  $a->setAttributes($attributes);
980  }
981 
982  // generate the NameID for the assertion
983  if (isset($state['saml:NameIDFormat'])) {
984  $nameIdFormat = $state['saml:NameIDFormat'];
985  } else {
986  $nameIdFormat = null;
987  }
988 
989  if ($nameIdFormat === null || !isset($state['saml:NameID'][$nameIdFormat])) {
990  // either not set in request, or not set to a format we supply. Fall back to old generation method
991  $nameIdFormat = $spMetadata->getString('NameIDFormat', null);
992  if ($nameIdFormat === null) {
993  $nameIdFormat = $idpMetadata->getString('NameIDFormat', \SAML2\Constants::NAMEID_TRANSIENT);
994  }
995  }
996 
997  if (isset($state['saml:NameID'][$nameIdFormat])) {
998  $nameId = $state['saml:NameID'][$nameIdFormat];
999  $nameId->Format = $nameIdFormat;
1000  } else {
1001  $spNameQualifier = $spMetadata->getString('SPNameQualifier', null);
1002  if ($spNameQualifier === null) {
1003  $spNameQualifier = $spMetadata->getString('entityid');
1004  }
1005 
1006  if ($nameIdFormat === \SAML2\Constants::NAMEID_TRANSIENT) {
1007  // generate a random id
1009  } else {
1010  /* this code will end up generating either a fixed assigned id (via nameid.attribute)
1011  or random id if not assigned/configured */
1012  $nameIdValue = self::generateNameIdValue($idpMetadata, $spMetadata, $state);
1013  if ($nameIdValue === null) {
1014  SimpleSAML\Logger::warning('Falling back to transient NameID.');
1015  $nameIdFormat = \SAML2\Constants::NAMEID_TRANSIENT;
1017  }
1018  }
1019 
1020  $nameId = new \SAML2\XML\saml\NameID();
1021  $nameId->Format = $nameIdFormat;
1022  $nameId->value = $nameIdValue;
1023  $nameId->SPNameQualifier = $spNameQualifier;
1024  }
1025 
1026  $state['saml:idp:NameID'] = $nameId;
1027 
1028  $a->setNameId($nameId);
1029 
1030  $encryptNameId = $spMetadata->getBoolean('nameid.encryption', null);
1031  if ($encryptNameId === null) {
1032  $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', false);
1033  }
1034  if ($encryptNameId) {
1035  $a->encryptNameId(sspmod_saml_Message::getEncryptionKey($spMetadata));
1036  }
1037 
1038  return $a;
1039  }
static generateID()
Generate a random identifier, ID_LENGTH bytes long.
Definition: Random.php:26
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
$assertionLifetime
$config
Definition: bootstrap.php:15
$sc SubjectConfirmationData
const CM_HOK
Holder-of-Key subject confirmation method.
Definition: Constants.php:65
$nameIdFormat
$nameIdValue
$nameId
Definition: saml2-acs.php:138
$encryptNameId
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
Attribute-related utility methods.
static warning($string)
Definition: Logger.php:177
const CM_BEARER
Bearer subject confirmation method.
Definition: Constants.php:60
$attributeNameFormat
static addSign(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata, \SAML2\SignedElement $element)
Add signature key and sender certificate to an element (Message or Assertion).
Definition: Message.php:20
getBoolean($name, $default=self::REQUIRED_OPTION)
This function retrieves a boolean configuration option.
if(array_key_exists('yes', $_REQUEST)) $attributes
Definition: getconsent.php:85
const NAMEID_TRANSIENT
Transient NameID format.
Definition: Constants.php:200
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.
Definition: Message.php:865
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.
+ Here is the call graph for this function:

◆ buildLogoutRequest()

static sspmod_saml_IdP_SAML2::buildLogoutRequest ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata,
array  $association,
  $relayState 
)
staticprivate

Build a logout request based on information in the metadata.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
array$associationThe SP association.
string | null$relayStateAn id that should be carried across the logout.
Returns
The corresponding SAML2 logout response.

Definition at line 1118 of file SAML2.php.

References $assertionLifetime, $encryptNameId, $lr, $relayState, sspmod_saml_Message\buildLogoutRequest(), SimpleSAML_Configuration\getBoolean(), sspmod_saml_Message\getEncryptionKey(), and SimpleSAML_Configuration\getInteger().

1123  {
1124 
1125  $lr = sspmod_saml_Message::buildLogoutRequest($idpMetadata, $spMetadata);
1126  $lr->setRelayState($relayState);
1127  $lr->setSessionIndex($association['saml:SessionIndex']);
1128  $lr->setNameId($association['saml:NameID']);
1129 
1130  $assertionLifetime = $spMetadata->getInteger('assertion.lifetime', null);
1131  if ($assertionLifetime === null) {
1132  $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300);
1133  }
1134  $lr->setNotOnOrAfter(time() + $assertionLifetime);
1135 
1136  $encryptNameId = $spMetadata->getBoolean('nameid.encryption', null);
1137  if ($encryptNameId === null) {
1138  $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', false);
1139  }
1140  if ($encryptNameId) {
1141  $lr->encryptNameId(sspmod_saml_Message::getEncryptionKey($spMetadata));
1142  }
1143 
1144  return $lr;
1145  }
$assertionLifetime
static buildLogoutRequest(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata)
Build a logout request based on information in the metadata.
Definition: Message.php:536
$encryptNameId
$relayState
getBoolean($name, $default=self::REQUIRED_OPTION)
This function retrieves a boolean configuration option.
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.
Definition: Message.php:865
if(!isset($associations[$assocId])) $association
$lr
+ Here is the call graph for this function:

◆ buildResponse()

static sspmod_saml_IdP_SAML2::buildResponse ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata,
  $consumerURL 
)
staticprivate

Build a authentication response based on information in the metadata.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
string$consumerURLThe Destination URL of the response.
Returns
The SAML2 response corresponding to the given data.

Definition at line 1157 of file SAML2.php.

References $r, sspmod_saml_Message\addSign(), SimpleSAML_Configuration\getBoolean(), and SimpleSAML_Configuration\getString().

1161  {
1162 
1163  $signResponse = $spMetadata->getBoolean('saml20.sign.response', null);
1164  if ($signResponse === null) {
1165  $signResponse = $idpMetadata->getBoolean('saml20.sign.response', true);
1166  }
1167 
1168  $r = new \SAML2\Response();
1169 
1170  $r->setIssuer($idpMetadata->getString('entityid'));
1171  $r->setDestination($consumerURL);
1172 
1173  if ($signResponse) {
1174  sspmod_saml_Message::addSign($idpMetadata, $spMetadata, $r);
1175  }
1176 
1177  return $r;
1178  }
$r
Definition: example_031.php:79
static addSign(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata, \SAML2\SignedElement $element)
Add signature key and sender certificate to an element (Message or Assertion).
Definition: Message.php:20
getBoolean($name, $default=self::REQUIRED_OPTION)
This function retrieves a boolean configuration option.
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
+ Here is the call graph for this function:

◆ encodeAttributes()

static sspmod_saml_IdP_SAML2::encodeAttributes ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata,
array  $attributes 
)
staticprivate

Helper function for encoding attributes.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
array$attributesThe attributes of the user.
Returns
array The encoded attributes.
Exceptions
SimpleSAML_Error_ExceptionIn case an unsupported encoding is specified by configuration.

Definition at line 743 of file SAML2.php.

References $name, $ret, $values, SAML2\DOMDocumentFactory\fromString(), SimpleSAML_Configuration\getArray(), and SimpleSAML_Configuration\getBoolean().

747  {
748 
749  $base64Attributes = $spMetadata->getBoolean('base64attributes', null);
750  if ($base64Attributes === null) {
751  $base64Attributes = $idpMetadata->getBoolean('base64attributes', false);
752  }
753 
754  if ($base64Attributes) {
755  $defaultEncoding = 'base64';
756  } else {
757  $defaultEncoding = 'string';
758  }
759 
760  $srcEncodings = $idpMetadata->getArray('attributeencodings', array());
761  $dstEncodings = $spMetadata->getArray('attributeencodings', array());
762 
763  /*
764  * Merge the two encoding arrays. Encodings specified in the target metadata
765  * takes precedence over the source metadata.
766  */
767  $encodings = array_merge($srcEncodings, $dstEncodings);
768 
769  $ret = array();
770  foreach ($attributes as $name => $values) {
771  $ret[$name] = array();
772  if (array_key_exists($name, $encodings)) {
773  $encoding = $encodings[$name];
774  } else {
775  $encoding = $defaultEncoding;
776  }
777 
778  foreach ($values as $value) {
779  // allow null values
780  if ($value === null) {
781  $ret[$name][] = $value;
782  continue;
783  }
784 
785  $attrval = $value;
786  if ($value instanceof DOMNodeList) {
787  $attrval = new \SAML2\XML\saml\AttributeValue($value->item(0)->parentNode);
788  }
789 
790  switch ($encoding) {
791  case 'string':
792  $value = (string) $attrval;
793  break;
794  case 'base64':
795  $value = base64_encode((string) $attrval);
796  break;
797  case 'raw':
798  if (is_string($value)) {
799  $doc = \SAML2\DOMDocumentFactory::fromString('<root>'.$value.'</root>');
800  $value = $doc->firstChild->childNodes;
801  }
802  assert($value instanceof DOMNodeList || $value instanceof \SAML2\XML\saml\NameID);
803  break;
804  default:
805  throw new SimpleSAML_Error_Exception('Invalid encoding for attribute '.
806  var_export($name, true).': '.var_export($encoding, true));
807  }
808  $ret[$name][] = $value;
809  }
810  }
811 
812  return $ret;
813  }
getArray($name, $default=self::REQUIRED_OPTION)
This function retrieves an array configuration option.
$values
getBoolean($name, $default=self::REQUIRED_OPTION)
This function retrieves a boolean configuration option.
if(array_key_exists('yes', $_REQUEST)) $attributes
Definition: getconsent.php:85
$ret
Definition: parser.php:6
+ Here is the call graph for this function:

◆ encryptAssertion()

static sspmod_saml_IdP_SAML2::encryptAssertion ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata,
\SAML2\Assertion  $assertion 
)
staticprivate

Encrypt an assertion.

This function takes in a and encrypts it if encryption of assertions are enabled in the metadata.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
\SAML2\Assertion$assertionThe assertion we are encrypting.
Returns
| The assertion.
Exceptions
SimpleSAML_Error_ExceptionIn case the encryption key type is not supported.

Definition at line 1056 of file SAML2.php.

References $key, $keys, SimpleSAML_Configuration\getBoolean(), SimpleSAML_Configuration\getPublicKeys(), and SimpleSAML_Configuration\getString().

1060  {
1061 
1062  $encryptAssertion = $spMetadata->getBoolean('assertion.encryption', null);
1063  if ($encryptAssertion === null) {
1064  $encryptAssertion = $idpMetadata->getBoolean('assertion.encryption', false);
1065  }
1066  if (!$encryptAssertion) {
1067  // we are _not_ encrypting this assertion, and are therefore done
1068  return $assertion;
1069  }
1070 
1071 
1072  $sharedKey = $spMetadata->getString('sharedkey', null);
1073  if ($sharedKey !== null) {
1074  $key = new XMLSecurityKey(XMLSecurityKey::AES128_CBC);
1075  $key->loadKey($sharedKey);
1076  } else {
1077  $keys = $spMetadata->getPublicKeys('encryption', true);
1078  if (!empty($keys)) {
1079  $key = $keys[0];
1080  switch ($key['type']) {
1081  case 'X509Certificate':
1082  $pemKey = "-----BEGIN CERTIFICATE-----\n".
1083  chunk_split($key['X509Certificate'], 64).
1084  "-----END CERTIFICATE-----\n";
1085  break;
1086  default:
1087  throw new SimpleSAML_Error_Exception('Unsupported encryption key type: '.$key['type']);
1088  }
1089 
1090  // extract the public key from the certificate for encryption
1091  $key = new XMLSecurityKey(XMLSecurityKey::RSA_OAEP_MGF1P, array('type' => 'public'));
1092  $key->loadKey($pemKey);
1093  } else {
1094  throw new SimpleSAML_Error_ConfigurationError(
1095  'Missing encryption key for entity `' . $spMetadata->getString('entityid') . '`',
1096  null,
1097  $spMetadata->getString('metadata-set') . '.php'
1098  );
1099  }
1100  }
1101 
1102  $ea = new \SAML2\EncryptedAssertion();
1103  $ea->setAssertion($assertion, $key);
1104  return $ea;
1105  }
$keys
getBoolean($name, $default=self::REQUIRED_OPTION)
This function retrieves a boolean configuration option.
getPublicKeys($use=null, $required=false, $prefix='')
Get public key from metadata.
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
$key
Definition: croninfo.php:18
+ Here is the call graph for this function:

◆ generateNameIdValue()

static sspmod_saml_IdP_SAML2::generateNameIdValue ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata,
array &  $state 
)
staticprivate

Calculate the NameID value that should be used.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
array&$stateThe authentication state of the user.
Returns
string The NameID value.

Definition at line 691 of file SAML2.php.

References $attributes, $idpEntityId, $spEntityId, SimpleSAML\Logger\error(), SimpleSAML\Utils\Config\getSecretSalt(), SimpleSAML_Configuration\getString(), and GuzzleHttp\Psr7\hash().

695  {
696 
697  $attribute = $spMetadata->getString('simplesaml.nameidattribute', null);
698  if ($attribute === null) {
699  $attribute = $idpMetadata->getString('simplesaml.nameidattribute', null);
700  if ($attribute === null) {
701  if (!isset($state['UserID'])) {
702  SimpleSAML\Logger::error('Unable to generate NameID. Check the userid.attribute option.');
703  return null;
704  }
705  $attributeValue = $state['UserID'];
706  $idpEntityId = $idpMetadata->getString('entityid');
707  $spEntityId = $spMetadata->getString('entityid');
708 
710 
711  $uidData = 'uidhashbase'.$secretSalt;
712  $uidData .= strlen($idpEntityId).':'.$idpEntityId;
713  $uidData .= strlen($spEntityId).':'.$spEntityId;
714  $uidData .= strlen($attributeValue).':'.$attributeValue;
715  $uidData .= $secretSalt;
716 
717  return hash('sha1', $uidData);
718  }
719  }
720 
721  $attributes = $state['Attributes'];
722  if (!array_key_exists($attribute, $attributes)) {
723  SimpleSAML\Logger::error('Unable to add NameID: Missing '.var_export($attribute, true).
724  ' in the attributes of the user.');
725  return null;
726  }
727 
728  return $attributes[$attribute][0];
729  }
$idpEntityId
Definition: prp.php:12
$spEntityId
static getSecretSalt()
Retrieve the secret salt.
Definition: Config.php:49
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
static error($string)
Definition: Logger.php:166
if(array_key_exists('yes', $_REQUEST)) $attributes
Definition: getconsent.php:85
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
hash(StreamInterface $stream, $algo, $rawOutput=false)
Calculate a hash of a Stream.
Definition: functions.php:406
+ Here is the call graph for this function:

◆ getAssertionConsumerService()

static sspmod_saml_IdP_SAML2::getAssertionConsumerService ( array  $supportedBindings,
SimpleSAML_Configuration  $spMetadata,
  $AssertionConsumerServiceURL,
  $ProtocolBinding,
  $AssertionConsumerServiceIndex 
)
staticprivate

Find SP AssertionConsumerService based on parameter in AuthnRequest.

Parameters
array$supportedBindingsThe bindings we allow for the response.
SimpleSAML_Configuration$spMetadataThe metadata for the SP.
string | NULL$AssertionConsumerServiceURLAssertionConsumerServiceURL from request.
string | NULL$ProtocolBindingProtocolBinding from request.
int | NULL$AssertionConsumerServiceIndexAssertionConsumerServiceIndex from request.
Returns
array Array with the Location and Binding we should use for the response.

Definition at line 162 of file SAML2.php.

References SimpleSAML_Configuration\getDefaultEndpoint(), SimpleSAML_Configuration\getEndpoints(), and SimpleSAML\Logger\warning().

168  {
169  assert(is_string($AssertionConsumerServiceURL) || $AssertionConsumerServiceURL === null);
170  assert(is_string($ProtocolBinding) || $ProtocolBinding === null);
171  assert(is_int($AssertionConsumerServiceIndex) || $AssertionConsumerServiceIndex === null);
172 
173  /* We want to pick the best matching endpoint in the case where for example
174  * only the ProtocolBinding is given. We therefore pick endpoints with the
175  * following priority:
176  * 1. isDefault="true"
177  * 2. isDefault unset
178  * 3. isDefault="false"
179  */
180  $firstNotFalse = null;
181  $firstFalse = null;
182  foreach ($spMetadata->getEndpoints('AssertionConsumerService') as $ep) {
183  if ($AssertionConsumerServiceURL !== null && $ep['Location'] !== $AssertionConsumerServiceURL) {
184  continue;
185  }
186  if ($ProtocolBinding !== null && $ep['Binding'] !== $ProtocolBinding) {
187  continue;
188  }
189  if ($AssertionConsumerServiceIndex !== null && $ep['index'] !== $AssertionConsumerServiceIndex) {
190  continue;
191  }
192 
193  if (!in_array($ep['Binding'], $supportedBindings, true)) {
194  /* The endpoint has an unsupported binding. */
195  continue;
196  }
197 
198  // we have an endpoint that matches all our requirements. Check if it is the best one
199 
200  if (array_key_exists('isDefault', $ep)) {
201  if ($ep['isDefault'] === true) {
202  // this is the first matching endpoint with isDefault set to true
203  return $ep;
204  }
205  // isDefault is set to FALSE, but the endpoint is still usable
206  if ($firstFalse === null) {
207  // this is the first endpoint that we can use
208  $firstFalse = $ep;
209  }
210  } else {
211  if ($firstNotFalse === null) {
212  // this is the first endpoint without isDefault set
213  $firstNotFalse = $ep;
214  }
215  }
216  }
217 
218  if ($firstNotFalse !== null) {
219  return $firstNotFalse;
220  } elseif ($firstFalse !== null) {
221  return $firstFalse;
222  }
223 
224  SimpleSAML\Logger::warning('Authentication request specifies invalid AssertionConsumerService:');
225  if ($AssertionConsumerServiceURL !== null) {
226  SimpleSAML\Logger::warning('AssertionConsumerServiceURL: '.var_export($AssertionConsumerServiceURL, true));
227  }
228  if ($ProtocolBinding !== null) {
229  SimpleSAML\Logger::warning('ProtocolBinding: '.var_export($ProtocolBinding, true));
230  }
231  if ($AssertionConsumerServiceIndex !== null) {
233  'AssertionConsumerServiceIndex: '.var_export($AssertionConsumerServiceIndex, true)
234  );
235  }
236 
237  // we have no good endpoints. Our last resort is to just use the default endpoint
238  return $spMetadata->getDefaultEndpoint('AssertionConsumerService', $supportedBindings);
239  }
getEndpoints($endpointType)
Helper function for dealing with metadata endpoints.
getDefaultEndpoint($endpointType, array $bindings=null, $default=self::REQUIRED_OPTION)
Find the default endpoint of the given type.
static warning($string)
Definition: Logger.php:177
+ Here is the call graph for this function:

◆ getAssociationConfig()

static sspmod_saml_IdP_SAML2::getAssociationConfig ( SimpleSAML_IdP  $idp,
array  $association 
)
static

Retrieve the metadata for the given SP association.

Parameters
SimpleSAML_IdP$idpThe IdP the association belongs to.
array$associationThe SP association.
Returns
SimpleSAML_Configuration Configuration object for the SP metadata.

Definition at line 671 of file SAML2.php.

References $metadata, SimpleSAML_Metadata_MetaDataStorageHandler\getMetadataHandler(), and SimpleSAML_Configuration\loadFromArray().

672  {
674  try {
675  return $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote');
676  } catch (Exception $e) {
677  return SimpleSAML_Configuration::loadFromArray(array(), 'Unknown SAML 2 entity.');
678  }
679  }
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
$metadata['__DYNAMIC:1__']
if(!isset($associations[$assocId])) $association
static loadFromArray($config, $location='[ARRAY]', $instance=null)
Loads a configuration from the given array.
+ Here is the call graph for this function:

◆ getAttributeNameFormat()

static sspmod_saml_IdP_SAML2::getAttributeNameFormat ( SimpleSAML_Configuration  $idpMetadata,
SimpleSAML_Configuration  $spMetadata 
)
staticprivate

Determine which NameFormat we should use for attributes.

Parameters
SimpleSAML_Configuration$idpMetadataThe metadata of the IdP.
SimpleSAML_Configuration$spMetadataThe metadata of the SP.
Returns
string The NameFormat.

Definition at line 824 of file SAML2.php.

References $attributeNameFormat, and SimpleSAML_Configuration\getString().

827  {
828 
829  // try SP metadata first
830  $attributeNameFormat = $spMetadata->getString('attributes.NameFormat', null);
831  if ($attributeNameFormat !== null) {
832  return $attributeNameFormat;
833  }
834  $attributeNameFormat = $spMetadata->getString('AttributeNameFormat', null);
835  if ($attributeNameFormat !== null) {
836  return $attributeNameFormat;
837  }
838 
839  // look in IdP metadata
840  $attributeNameFormat = $idpMetadata->getString('attributes.NameFormat', null);
841  if ($attributeNameFormat !== null) {
842  return $attributeNameFormat;
843  }
844  $attributeNameFormat = $idpMetadata->getString('AttributeNameFormat', null);
845  if ($attributeNameFormat !== null) {
846  return $attributeNameFormat;
847  }
848 
849  // default
850  return 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic';
851  }
$attributeNameFormat
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
+ Here is the call graph for this function:

◆ getLogoutURL()

static sspmod_saml_IdP_SAML2::getLogoutURL ( SimpleSAML_IdP  $idp,
array  $association,
  $relayState 
)
static

Retrieve a logout URL for a given logout association.

Parameters
SimpleSAML_IdP$idpThe IdP we are sending a logout request from.
array$associationThe association that should be terminated.
string | NULL$relayStateAn id that should be carried across the logout.
Returns
string The logout URL.

Definition at line 631 of file SAML2.php.

References $binding, $bindings, $dst, $idpMetadata, $lr, $metadata, PHPMailer\PHPMailer\$params, $relayState, $spMetadata, SimpleSAML_IdP\getConfig(), SimpleSAML_IdP\getId(), SimpleSAML_Metadata_MetaDataStorageHandler\getMetadataHandler(), SimpleSAML\Module\getModuleURL(), and SimpleSAML\Logger\info().

632  {
633  assert(is_string($relayState) || $relayState === null);
634 
635  SimpleSAML\Logger::info('Sending SAML 2.0 LogoutRequest to: '.var_export($association['saml:entityID'], true));
636 
638  $idpMetadata = $idp->getConfig();
639  $spMetadata = $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote');
640 
641  $bindings = array(
642  \SAML2\Constants::BINDING_HTTP_REDIRECT,
643  \SAML2\Constants::BINDING_HTTP_POST
644  );
645  $dst = $spMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', $bindings);
646 
647  if ($dst['Binding'] === \SAML2\Constants::BINDING_HTTP_POST) {
648  $params = array('association' => $association['id'], 'idp' => $idp->getId());
649  if ($relayState !== null) {
650  $params['RelayState'] = $relayState;
651  }
652  return SimpleSAML\Module::getModuleURL('core/idp/logout-iframe-post.php', $params);
653  }
654 
655  $lr = self::buildLogoutRequest($idpMetadata, $spMetadata, $association, $relayState);
656  $lr->setDestination($dst['Location']);
657 
658  $binding = new \SAML2\HTTPRedirect();
659  return $binding->getRedirectURL($lr);
660  }
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
$dst
$spMetadata
$metadata['__DYNAMIC:1__']
$bindings
static getModuleURL($resource, array $parameters=array())
Get absolute URL to a specified module resource.
Definition: Module.php:220
static info($string)
Definition: Logger.php:199
$relayState
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
getId()
Retrieve the ID of this IdP.
Definition: IdP.php:111
if(!isset($associations[$assocId])) $association
$lr
$idpMetadata
$binding
+ Here is the call graph for this function:

◆ handleAuthError()

static sspmod_saml_IdP_SAML2::handleAuthError ( SimpleSAML_Error_Exception  $exception,
array  $state 
)
static

Handle authentication error.

SimpleSAML_Error_Exception $exception The exception.

Parameters
array$stateThe error state.

Definition at line 96 of file SAML2.php.

References $binding, $idp, $idpMetadata, $relayState, $spEntityId, $spMetadata, sspmod_saml_Error\fromException(), SAML2\Binding\getBinding(), SimpleSAML_IdP\getByState(), SimpleSAML_Configuration\loadFromArray(), SimpleSAML_Stats\log(), SimpleSAML_Error_Exception\log(), and SimpleSAML\Logger\warning().

97  {
98  assert(isset($state['SPMetadata']));
99  assert(isset($state['saml:ConsumerURL']));
100  assert(array_key_exists('saml:RequestId', $state)); // Can be NULL.
101  assert(array_key_exists('saml:RelayState', $state)); // Can be NULL.
102 
103  $spMetadata = $state["SPMetadata"];
104  $spEntityId = $spMetadata['entityid'];
106  $spMetadata,
107  '$metadata['.var_export($spEntityId, true).']'
108  );
109 
110  $requestId = $state['saml:RequestId'];
111  $relayState = $state['saml:RelayState'];
112  $consumerURL = $state['saml:ConsumerURL'];
113  $protocolBinding = $state['saml:Binding'];
114 
116 
117  $idpMetadata = $idp->getConfig();
118 
119  $error = sspmod_saml_Error::fromException($exception);
120 
121  SimpleSAML\Logger::warning("Returning error to SP with entity ID '".var_export($spEntityId, true)."'.");
122  $exception->log(SimpleSAML\Logger::WARNING);
123 
124  $ar = self::buildResponse($idpMetadata, $spMetadata, $consumerURL);
125  $ar->setInResponseTo($requestId);
126  $ar->setRelayState($relayState);
127 
128  $status = array(
129  'Code' => $error->getStatus(),
130  'SubCode' => $error->getSubStatus(),
131  'Message' => $error->getStatusMessage(),
132  );
133  $ar->setStatus($status);
134 
135  $statsData = array(
136  'spEntityID' => $spEntityId,
137  'idpEntityID' => $idpMetadata->getString('entityid'),
138  'protocol' => 'saml2',
139  'error' => $status,
140  );
141  if (isset($state['saml:AuthnRequestReceivedAt'])) {
142  $statsData['logintime'] = microtime(true) - $state['saml:AuthnRequestReceivedAt'];
143  }
144  SimpleSAML_Stats::log('saml:idp:Response:error', $statsData);
145 
146  $binding = \SAML2\Binding::getBinding($protocolBinding);
147  $binding->send($ar);
148  }
static getByState(array &$state)
Retrieve the IdP "owning" the state.
Definition: IdP.php:145
log($default_level)
Print the exception to the log, by default with log level error.
Definition: Exception.php:235
static getBinding($urn)
Retrieve a binding with the given URN.
Definition: Binding.php:28
$spEntityId
$spMetadata
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
Attribute-related utility methods.
$relayState
static warning($string)
Definition: Logger.php:177
static fromException(Exception $exception)
Create a SAML2 error from an exception.
Definition: Error.php:103
$idp
Definition: prp.php:13
$idpMetadata
$binding
static loadFromArray($config, $location='[ARRAY]', $instance=null)
Loads a configuration from the given array.
static log($event, array $data=array())
Notify about an event.
Definition: Stats.php:71
+ Here is the call graph for this function:

◆ processSOAPAuthnRequest()

static sspmod_saml_IdP_SAML2::processSOAPAuthnRequest ( array &  $state)
static

Definition at line 443 of file SAML2.php.

References $_SERVER, and SimpleSAML\Logger\error().

444  {
445  if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
446  SimpleSAML\Logger::error("ECP AuthnRequest did not contain Basic Authentication header");
447  // TODO Throw some sort of ECP-specific exception / convert this to SOAP fault
448  throw new SimpleSAML_Error_Error("WRONGUSERPASS");
449  }
450 
451  $state['core:auth:username'] = $_SERVER['PHP_AUTH_USER'];
452  $state['core:auth:password'] = $_SERVER['PHP_AUTH_PW'];
453  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
static error($string)
Definition: Logger.php:166
+ Here is the call graph for this function:

◆ receiveAuthnRequest()

static sspmod_saml_IdP_SAML2::receiveAuthnRequest ( SimpleSAML_IdP  $idp)
static

Receive an authentication request.

Parameters
SimpleSAML_IdP$idpThe IdP we are receiving it for.
Exceptions
SimpleSAML_Error_BadRequestIn case an error occurs when trying to receive the request.

Definition at line 248 of file SAML2.php.

References $binding, $idpMetadata, $metadata, $relayState, $request, $spEntityId, $spMetadata, $state, SAML2\Constants\BINDING_HOK_SSO, SAML2\Constants\BINDING_HTTP_ARTIFACT, SAML2\Constants\BINDING_PAOS, SimpleSAML\Utils\HTTP\checkSessionCookie(), SimpleSAML_Auth_State\EXCEPTION_HANDLER_FUNC, SimpleSAML_IdP\getConfig(), SAML2\Binding\getCurrentBinding(), SimpleSAML_Metadata_MetaDataStorageHandler\getMetadataHandler(), SimpleSAML_IdP\handleAuthenticationRequest(), SimpleSAML\Logger\info(), SimpleSAML_Stats\log(), SimpleSAML_Auth_State\RESTART, and sspmod_saml_Message\validateMessage().

249  {
250 
252  $idpMetadata = $idp->getConfig();
253 
254  $supportedBindings = array(\SAML2\Constants::BINDING_HTTP_POST);
255  if ($idpMetadata->getBoolean('saml20.sendartifact', false)) {
256  $supportedBindings[] = \SAML2\Constants::BINDING_HTTP_ARTIFACT;
257  }
258  if ($idpMetadata->getBoolean('saml20.hok.assertion', false)) {
259  $supportedBindings[] = \SAML2\Constants::BINDING_HOK_SSO;
260  }
261  if ($idpMetadata->getBoolean('saml20.ecp', false)) {
262  $supportedBindings[] = \SAML2\Constants::BINDING_PAOS;
263  }
264 
265  if (isset($_REQUEST['spentityid'])) {
266  /* IdP initiated authentication. */
267 
268  if (isset($_REQUEST['cookieTime'])) {
269  $cookieTime = (int) $_REQUEST['cookieTime'];
270  if ($cookieTime + 5 > time()) {
271  /*
272  * Less than five seconds has passed since we were
273  * here the last time. Cookies are probably disabled.
274  */
275  \SimpleSAML\Utils\HTTP::checkSessionCookie(\SimpleSAML\Utils\HTTP::getSelfURL());
276  }
277  }
278 
279  $spEntityId = (string) $_REQUEST['spentityid'];
280  $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
281 
282  if (isset($_REQUEST['RelayState'])) {
283  $relayState = (string) $_REQUEST['RelayState'];
284  } else {
285  $relayState = null;
286  }
287 
288  if (isset($_REQUEST['binding'])) {
289  $protocolBinding = (string) $_REQUEST['binding'];
290  } else {
291  $protocolBinding = null;
292  }
293 
294  if (isset($_REQUEST['NameIDFormat'])) {
295  $nameIDFormat = (string) $_REQUEST['NameIDFormat'];
296  } else {
297  $nameIDFormat = null;
298  }
299 
300  $requestId = null;
301  $IDPList = array();
302  $ProxyCount = null;
303  $RequesterID = null;
304  $forceAuthn = false;
305  $isPassive = false;
306  $consumerURL = null;
307  $consumerIndex = null;
308  $extensions = null;
309  $allowCreate = true;
310  $authnContext = null;
311  $binding = null;
312 
313  $idpInit = true;
314 
316  'SAML2.0 - IdP.SSOService: IdP initiated authentication: '.var_export($spEntityId, true)
317  );
318  } else {
320  $request = $binding->receive();
321 
322  if (!($request instanceof \SAML2\AuthnRequest)) {
323  throw new SimpleSAML_Error_BadRequest(
324  'Message received on authentication request endpoint wasn\'t an authentication request.'
325  );
326  }
327 
328  $spEntityId = $request->getIssuer();
329  if ($spEntityId === null) {
330  throw new SimpleSAML_Error_BadRequest(
331  'Received message on authentication request endpoint without issuer.'
332  );
333  }
334  $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
335 
337 
338  $relayState = $request->getRelayState();
339 
340  $requestId = $request->getId();
341  $IDPList = $request->getIDPList();
342  $ProxyCount = $request->getProxyCount();
343  if ($ProxyCount !== null) {
344  $ProxyCount--;
345  }
346  $RequesterID = $request->getRequesterID();
347  $forceAuthn = $request->getForceAuthn();
348  $isPassive = $request->getIsPassive();
349  $consumerURL = $request->getAssertionConsumerServiceURL();
350  $protocolBinding = $request->getProtocolBinding();
351  $consumerIndex = $request->getAssertionConsumerServiceIndex();
352  $extensions = $request->getExtensions();
353  $authnContext = $request->getRequestedAuthnContext();
354 
355  $nameIdPolicy = $request->getNameIdPolicy();
356  if (isset($nameIdPolicy['Format'])) {
357  $nameIDFormat = $nameIdPolicy['Format'];
358  } else {
359  $nameIDFormat = null;
360  }
361  if (isset($nameIdPolicy['AllowCreate'])) {
362  $allowCreate = $nameIdPolicy['AllowCreate'];
363  } else {
364  $allowCreate = false;
365  }
366 
367  $idpInit = false;
368 
370  'SAML2.0 - IdP.SSOService: incoming authentication request: '.var_export($spEntityId, true)
371  );
372  }
373 
374  SimpleSAML_Stats::log('saml:idp:AuthnRequest', array(
375  'spEntityID' => $spEntityId,
376  'idpEntityID' => $idpMetadata->getString('entityid'),
377  'forceAuthn' => $forceAuthn,
378  'isPassive' => $isPassive,
379  'protocol' => 'saml2',
380  'idpInit' => $idpInit,
381  ));
382 
383  $acsEndpoint = self::getAssertionConsumerService(
384  $supportedBindings,
385  $spMetadata,
386  $consumerURL,
387  $protocolBinding,
388  $consumerIndex
389  );
390 
391  $IDPList = array_unique(array_merge($IDPList, $spMetadata->getArrayizeString('IDPList', array())));
392  if ($ProxyCount === null) {
393  $ProxyCount = $spMetadata->getInteger('ProxyCount', null);
394  }
395 
396  if (!$forceAuthn) {
397  $forceAuthn = $spMetadata->getBoolean('ForceAuthn', false);
398  }
399 
400  $sessionLostParams = array(
401  'spentityid' => $spEntityId,
402  'cookieTime' => time(),
403  );
404  if ($relayState !== null) {
405  $sessionLostParams['RelayState'] = $relayState;
406  }
407 
408  $sessionLostURL = \SimpleSAML\Utils\HTTP::addURLParameters(
409  \SimpleSAML\Utils\HTTP::getSelfURLNoQuery(),
410  $sessionLostParams
411  );
412 
413  $state = array(
414  'Responder' => array('sspmod_saml_IdP_SAML2', 'sendResponse'),
415  SimpleSAML_Auth_State::EXCEPTION_HANDLER_FUNC => array('sspmod_saml_IdP_SAML2', 'handleAuthError'),
416  SimpleSAML_Auth_State::RESTART => $sessionLostURL,
417 
418  'SPMetadata' => $spMetadata->toArray(),
419  'saml:RelayState' => $relayState,
420  'saml:RequestId' => $requestId,
421  'saml:IDPList' => $IDPList,
422  'saml:ProxyCount' => $ProxyCount,
423  'saml:RequesterID' => $RequesterID,
424  'ForceAuthn' => $forceAuthn,
425  'isPassive' => $isPassive,
426  'saml:ConsumerURL' => $acsEndpoint['Location'],
427  'saml:Binding' => $acsEndpoint['Binding'],
428  'saml:NameIDFormat' => $nameIDFormat,
429  'saml:AllowCreate' => $allowCreate,
430  'saml:Extensions' => $extensions,
431  'saml:AuthnRequestReceivedAt' => microtime(true),
432  'saml:RequestedAuthnContext' => $authnContext,
433  );
434 
435  // ECP AuthnRequests need to supply credentials
436  if ($binding instanceof SOAP) {
437  self::processSOAPAuthnRequest($state);
438  }
439 
441  }
const BINDING_HOK_SSO
The URN for the Holder-of-Key Web Browser SSO Profile binding.
Definition: Constants.php:55
handleAuthenticationRequest(array &$state)
Process authentication requests.
Definition: IdP.php:377
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
static validateMessage(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata, \SAML2\Message $message)
Check signature on a SAML2 message if enabled.
Definition: Message.php:236
const RESTART
The index in the state array which contains the restart URL.
Definition: State.php:57
foreach($paths as $path) $request
Definition: asyncclient.php:32
$spEntityId
static getCurrentBinding()
Guess the current binding.
Definition: Binding.php:62
$spMetadata
$metadata['__DYNAMIC:1__']
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
Attribute-related utility methods.
static info($string)
Definition: Logger.php:199
$relayState
const EXCEPTION_HANDLER_FUNC
The index in the state array which contains the exception handler function.
Definition: State.php:69
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
const BINDING_PAOS
The URN for the PAOS binding.
Definition: Constants.php:50
const BINDING_HTTP_ARTIFACT
The URN for the HTTP-ARTIFACT binding.
Definition: Constants.php:40
$idpMetadata
static checkSessionCookie($retryURL=null)
Check for session cookie, and show missing-cookie page if it is missing.
Definition: HTTP.php:286
$binding
static log($event, array $data=array())
Notify about an event.
Definition: Stats.php:71
+ Here is the call graph for this function:

◆ receiveLogoutMessage()

static sspmod_saml_IdP_SAML2::receiveLogoutMessage ( SimpleSAML_IdP  $idp)
static

Receive a logout message.

Parameters
SimpleSAML_IdP$idpThe IdP we are receiving it for.
Exceptions
SimpleSAML_Error_BadRequestIn case an error occurs while trying to receive the logout message.

Definition at line 556 of file SAML2.php.

References $assocId, $binding, $idpMetadata, $message, $metadata, $relayState, $spEntityId, $spMetadata, $state, SimpleSAML_IdP\getConfig(), SAML2\Binding\getCurrentBinding(), SimpleSAML_Metadata_MetaDataStorageHandler\getMetadataHandler(), sspmod_saml_Message\getResponseError(), SimpleSAML_IdP\handleLogoutRequest(), SimpleSAML_IdP\handleLogoutResponse(), SimpleSAML\Logger\info(), SimpleSAML_Stats\log(), SimpleSAML\Logger\stats(), sspmod_saml_Message\validateMessage(), and SimpleSAML\Logger\warning().

557  {
558 
560  $message = $binding->receive();
561 
562  $spEntityId = $message->getIssuer();
563  if ($spEntityId === null) {
564  /* Without an issuer we have no way to respond to the message. */
565  throw new SimpleSAML_Error_BadRequest('Received message on logout endpoint without issuer.');
566  }
567 
569  $idpMetadata = $idp->getConfig();
570  $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
571 
573 
574  if ($message instanceof \SAML2\LogoutResponse) {
575  SimpleSAML\Logger::info('Received SAML 2.0 LogoutResponse from: '.var_export($spEntityId, true));
576  $statsData = array(
577  'spEntityID' => $spEntityId,
578  'idpEntityID' => $idpMetadata->getString('entityid'),
579  );
580  if (!$message->isSuccess()) {
581  $statsData['error'] = $message->getStatus();
582  }
583  SimpleSAML_Stats::log('saml:idp:LogoutResponse:recv', $statsData);
584 
585  $relayState = $message->getRelayState();
586 
587  if (!$message->isSuccess()) {
589  SimpleSAML\Logger::warning('Unsuccessful logout. Status was: '.$logoutError);
590  } else {
591  $logoutError = null;
592  }
593 
594  $assocId = 'saml:'.$spEntityId;
595 
596  $idp->handleLogoutResponse($assocId, $relayState, $logoutError);
597  } elseif ($message instanceof \SAML2\LogoutRequest) {
598  SimpleSAML\Logger::info('Received SAML 2.0 LogoutRequest from: '.var_export($spEntityId, true));
599  SimpleSAML_Stats::log('saml:idp:LogoutRequest:recv', array(
600  'spEntityID' => $spEntityId,
601  'idpEntityID' => $idpMetadata->getString('entityid'),
602  ));
603 
604  $spStatsId = $spMetadata->getString('core:statistics-id', $spEntityId);
605  SimpleSAML\Logger::stats('saml20-idp-SLO spinit '.$spStatsId.' '.$idpMetadata->getString('entityid'));
606 
607  $state = array(
608  'Responder' => array('sspmod_saml_IdP_SAML2', 'sendLogoutResponse'),
609  'saml:SPEntityId' => $spEntityId,
610  'saml:RelayState' => $message->getRelayState(),
611  'saml:RequestId' => $message->getId(),
612  );
613 
614  $assocId = 'saml:'.$spEntityId;
615  $idp->handleLogoutRequest($state, $assocId);
616  } else {
617  throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: '.get_class($message));
618  }
619  }
handleLogoutRequest(array &$state, $assocId)
Process a logout request.
Definition: IdP.php:472
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
static validateMessage(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata, \SAML2\Message $message)
Check signature on a SAML2 message if enabled.
Definition: Message.php:236
$spEntityId
static getCurrentBinding()
Guess the current binding.
Definition: Binding.php:62
$spMetadata
$metadata['__DYNAMIC:1__']
handleLogoutResponse($assocId, $relayState, SimpleSAML_Error_Exception $error=null)
Process a logout response.
Definition: IdP.php:507
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
static stats($string)
Definition: Logger.php:222
static info($string)
Definition: Logger.php:199
catch(Exception $e) $message
$relayState
static warning($string)
Definition: Logger.php:177
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
static getResponseError(\SAML2\StatusResponse $response)
Retrieve the status code of a response as a sspmod_saml_Error.
Definition: Message.php:452
$idpMetadata
if(!isset($_REQUEST['association'])) $assocId
$binding
static log($event, array $data=array())
Notify about an event.
Definition: Stats.php:71
+ Here is the call graph for this function:

◆ sendLogoutRequest()

static sspmod_saml_IdP_SAML2::sendLogoutRequest ( SimpleSAML_IdP  $idp,
array  $association,
  $relayState 
)
static

Send a logout request to a given association.

Parameters
SimpleSAML_IdP$idpThe IdP we are sending a logout request from.
array$associationThe association that should be terminated.
string | NULL$relayStateAn id that should be carried across the logout.

Definition at line 462 of file SAML2.php.

References $binding, $dst, $idpMetadata, $lr, $metadata, $relayState, $spMetadata, SAML2\Binding\getBinding(), SimpleSAML_IdP\getConfig(), SimpleSAML_Metadata_MetaDataStorageHandler\getMetadataHandler(), SimpleSAML\Logger\info(), and SimpleSAML_Stats\log().

463  {
464  assert(is_string($relayState) || $relayState === null);
465 
466  SimpleSAML\Logger::info('Sending SAML 2.0 LogoutRequest to: '.var_export($association['saml:entityID'], true));
467 
469  $idpMetadata = $idp->getConfig();
470  $spMetadata = $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote');
471 
472  SimpleSAML_Stats::log('saml:idp:LogoutRequest:sent', array(
473  'spEntityID' => $association['saml:entityID'],
474  'idpEntityID' => $idpMetadata->getString('entityid'),
475  ));
476 
477  $dst = $spMetadata->getEndpointPrioritizedByBinding(
478  'SingleLogoutService',
479  array(
480  \SAML2\Constants::BINDING_HTTP_REDIRECT,
481  \SAML2\Constants::BINDING_HTTP_POST
482  )
483  );
485  $lr = self::buildLogoutRequest($idpMetadata, $spMetadata, $association, $relayState);
486  $lr->setDestination($dst['Location']);
487 
488  $binding->send($lr);
489  }
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
$dst
static getBinding($urn)
Retrieve a binding with the given URN.
Definition: Binding.php:28
$spMetadata
$metadata['__DYNAMIC:1__']
static info($string)
Definition: Logger.php:199
$relayState
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
if(!isset($associations[$assocId])) $association
$lr
$idpMetadata
$binding
static log($event, array $data=array())
Notify about an event.
Definition: Stats.php:71
+ Here is the call graph for this function:

◆ sendLogoutResponse()

static sspmod_saml_IdP_SAML2::sendLogoutResponse ( SimpleSAML_IdP  $idp,
array  $state 
)
static

Send a logout response.

Parameters
SimpleSAML_IdP$idpThe IdP we are sending a logout request from.
array&$stateThe logout state array.

Definition at line 498 of file SAML2.php.

References $binding, $dst, $idpMetadata, $lr, $metadata, $spEntityId, $spMetadata, sspmod_saml_Message\buildLogoutResponse(), SimpleSAML\Logger\debug(), SAML2\Binding\getBinding(), SimpleSAML_IdP\getConfig(), SimpleSAML_Metadata_MetaDataStorageHandler\getMetadataHandler(), SimpleSAML\Logger\info(), and SimpleSAML_Stats\log().

499  {
500  assert(isset($state['saml:SPEntityId']));
501  assert(isset($state['saml:RequestId']));
502  assert(array_key_exists('saml:RelayState', $state)); // Can be NULL.
503 
504  $spEntityId = $state['saml:SPEntityId'];
505 
507  $idpMetadata = $idp->getConfig();
508  $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
509 
511  $lr->setInResponseTo($state['saml:RequestId']);
512  $lr->setRelayState($state['saml:RelayState']);
513 
514  if (isset($state['core:Failed']) && $state['core:Failed']) {
515  $partial = true;
516  $lr->setStatus(array(
517  'Code' => \SAML2\Constants::STATUS_SUCCESS,
518  'SubCode' => \SAML2\Constants::STATUS_PARTIAL_LOGOUT,
519  ));
520  SimpleSAML\Logger::info('Sending logout response for partial logout to SP '.var_export($spEntityId, true));
521  } else {
522  $partial = false;
523  SimpleSAML\Logger::debug('Sending logout response to SP '.var_export($spEntityId, true));
524  }
525 
526  SimpleSAML_Stats::log('saml:idp:LogoutResponse:sent', array(
527  'spEntityID' => $spEntityId,
528  'idpEntityID' => $idpMetadata->getString('entityid'),
529  'partial' => $partial
530  ));
531  $dst = $spMetadata->getEndpointPrioritizedByBinding(
532  'SingleLogoutService',
533  array(
534  \SAML2\Constants::BINDING_HTTP_REDIRECT,
535  \SAML2\Constants::BINDING_HTTP_POST
536  )
537  );
539  if (isset($dst['ResponseLocation'])) {
540  $dst = $dst['ResponseLocation'];
541  } else {
542  $dst = $dst['Location'];
543  }
544  $lr->setDestination($dst);
545 
546  $binding->send($lr);
547  }
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
$dst
static getBinding($urn)
Retrieve a binding with the given URN.
Definition: Binding.php:28
static debug($string)
Definition: Logger.php:211
$spEntityId
$spMetadata
$metadata['__DYNAMIC:1__']
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
static info($string)
Definition: Logger.php:199
getConfig()
Retrieve the configuration for this IdP.
Definition: IdP.php:158
$lr
$idpMetadata
$binding
static buildLogoutResponse(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata)
Build a logout response based on information in the metadata.
Definition: Message.php:556
static log($event, array $data=array())
Notify about an event.
Definition: Stats.php:71
+ Here is the call graph for this function:

◆ sendResponse()

static sspmod_saml_IdP_SAML2::sendResponse ( array  $state)
static

Send a response to the SP.

Parameters
array$stateThe authentication state.

Definition at line 19 of file SAML2.php.

References $association, $binding, $idp, $idpMetadata, $relayState, $spEntityId, $spMetadata, SAML2\Binding\getBinding(), SimpleSAML_IdP\getByState(), SimpleSAML\Logger\info(), SimpleSAML_Configuration\loadFromArray(), and SimpleSAML_Stats\log().

20  {
21  assert(isset($state['Attributes']));
22  assert(isset($state['SPMetadata']));
23  assert(isset($state['saml:ConsumerURL']));
24  assert(array_key_exists('saml:RequestId', $state)); // Can be NULL
25  assert(array_key_exists('saml:RelayState', $state)); // Can be NULL.
26 
27  $spMetadata = $state["SPMetadata"];
28  $spEntityId = $spMetadata['entityid'];
31  '$metadata['.var_export($spEntityId, true).']'
32  );
33 
34  SimpleSAML\Logger::info('Sending SAML 2.0 Response to '.var_export($spEntityId, true));
35 
36  $requestId = $state['saml:RequestId'];
37  $relayState = $state['saml:RelayState'];
38  $consumerURL = $state['saml:ConsumerURL'];
39  $protocolBinding = $state['saml:Binding'];
40 
42 
43  $idpMetadata = $idp->getConfig();
44 
45  $assertion = self::buildAssertion($idpMetadata, $spMetadata, $state);
46 
47  if (isset($state['saml:AuthenticatingAuthority'])) {
48  $assertion->setAuthenticatingAuthority($state['saml:AuthenticatingAuthority']);
49  }
50 
51  // create the session association (for logout)
52  $association = array(
53  'id' => 'saml:'.$spEntityId,
54  'Handler' => 'sspmod_saml_IdP_SAML2',
55  'Expires' => $assertion->getSessionNotOnOrAfter(),
56  'saml:entityID' => $spEntityId,
57  'saml:NameID' => $state['saml:idp:NameID'],
58  'saml:SessionIndex' => $assertion->getSessionIndex(),
59  );
60 
61  // maybe encrypt the assertion
62  $assertion = self::encryptAssertion($idpMetadata, $spMetadata, $assertion);
63 
64  // create the response
65  $ar = self::buildResponse($idpMetadata, $spMetadata, $consumerURL);
66  $ar->setInResponseTo($requestId);
67  $ar->setRelayState($relayState);
68  $ar->setAssertions(array($assertion));
69 
70  // register the session association with the IdP
71  $idp->addAssociation($association);
72 
73  $statsData = array(
74  'spEntityID' => $spEntityId,
75  'idpEntityID' => $idpMetadata->getString('entityid'),
76  'protocol' => 'saml2',
77  );
78  if (isset($state['saml:AuthnRequestReceivedAt'])) {
79  $statsData['logintime'] = microtime(true) - $state['saml:AuthnRequestReceivedAt'];
80  }
81  SimpleSAML_Stats::log('saml:idp:Response', $statsData);
82 
83  // send the response
84  $binding = \SAML2\Binding::getBinding($protocolBinding);
85  $binding->send($ar);
86  }
static getByState(array &$state)
Retrieve the IdP "owning" the state.
Definition: IdP.php:145
static getBinding($urn)
Retrieve a binding with the given URN.
Definition: Binding.php:28
$spEntityId
$spMetadata
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
static info($string)
Definition: Logger.php:199
$relayState
if(!isset($associations[$assocId])) $association
$idp
Definition: prp.php:13
$idpMetadata
$binding
static loadFromArray($config, $location='[ARRAY]', $instance=null)
Loads a configuration from the given array.
static log($event, array $data=array())
Notify about an event.
Definition: Stats.php:71
+ Here is the call graph for this function:

The documentation for this class was generated from the following file: