This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
spip-saml/inc/simplesamlphp/lib/SAML2/AuthnRequest.php

494 lines
12 KiB
PHP

<?php
/**
* Class for SAML 2 authentication request messages.
*
* @package simpleSAMLphp
* @version $Id$
*/
class SAML2_AuthnRequest extends SAML2_Request {
/**
* The options for what type of name identifier should be returned.
*
* @var array
*/
private $nameIdPolicy;
/**
* Whether the Identity Provider must authenticate the user again.
*
* @var bool
*/
private $forceAuthn;
/**
* Set to TRUE if this request is passive.
*
* @var bool.
*/
private $isPassive;
/**
* The list of providerIDs in this request's scoping element
*
* @var array
*/
private $IDPList = array();
/**
* The ProxyCount in this request's scoping element
*
* @var int
*/
private $ProxyCount = null;
/**
* The RequesterID list in this request's scoping element
*
* @var array
*/
private $RequesterID = array();
/**
* The URL of the asertion consumer service where the response should be delivered.
*
* @var string|NULL
*/
private $assertionConsumerServiceURL;
/**
* What binding should be used when sending the response.
*
* @var string|NULL
*/
private $protocolBinding;
/**
* The index of the AssertionConsumerService.
*
* @var int|NULL
*/
private $assertionConsumerServiceIndex;
/**
* What authentication context was requested.
*
* Array with the following elements.
* - AuthnContextClassRef (required)
* - Comparison (optinal)
*
* @var array
*/
private $requestedAuthnContext;
/**
* Request extensions.
*
* @var array
*/
private $extensions;
/**
* Constructor for SAML 2 authentication request messages.
*
* @param DOMElement|NULL $xml The input message.
*/
public function __construct(DOMElement $xml = NULL) {
parent::__construct('AuthnRequest', $xml);
$this->nameIdPolicy = array();
$this->forceAuthn = FALSE;
$this->isPassive = FALSE;
if ($xml === NULL) {
return;
}
$this->forceAuthn = SAML2_Utils::parseBoolean($xml, 'ForceAuthn', FALSE);
$this->isPassive = SAML2_Utils::parseBoolean($xml, 'IsPassive', FALSE);
if ($xml->hasAttribute('AssertionConsumerServiceURL')) {
$this->assertionConsumerServiceURL = $xml->getAttribute('AssertionConsumerServiceURL');
}
if ($xml->hasAttribute('ProtocolBinding')) {
$this->protocolBinding = $xml->getAttribute('ProtocolBinding');
}
if ($xml->hasAttribute('AssertionConsumerServiceIndex')) {
$this->assertionConsumerServiceIndex = (int)$xml->getAttribute('AssertionConsumerServiceIndex');
}
$nameIdPolicy = SAML2_Utils::xpQuery($xml, './saml_protocol:NameIDPolicy');
if (!empty($nameIdPolicy)) {
$nameIdPolicy = $nameIdPolicy[0];
if ($nameIdPolicy->hasAttribute('Format')) {
$this->nameIdPolicy['Format'] = $nameIdPolicy->getAttribute('Format');
}
if ($nameIdPolicy->hasAttribute('SPNameQualifier')) {
$this->nameIdPolicy['SPNameQualifier'] = $nameIdPolicy->getAttribute('SPNameQualifier');
}
if ($nameIdPolicy->hasAttribute('AllowCreate')) {
$this->nameIdPolicy['AllowCreate'] = SAML2_Utils::parseBoolean($nameIdPolicy, 'AllowCreate', FALSE);
}
}
$requestedAuthnContext = SAML2_Utils::xpQuery($xml, './saml_protocol:RequestedAuthnContext');
if (!empty($requestedAuthnContext)) {
$requestedAuthnContext = $requestedAuthnContext[0];
$rac = array(
'AuthnContextClassRef' => array(),
'Comparison' => 'exact',
);
$accr = SAML2_Utils::xpQuery($requestedAuthnContext, './saml_assertion:AuthnContextClassRef');
foreach ($accr as $i) {
$rac['AuthnContextClassRef'][] = trim($i->textContent);
}
if ($requestedAuthnContext->hasAttribute('Comparison')) {
$rac['Comparison'] = $requestedAuthnContext->getAttribute('Comparison');
}
$this->requestedAuthnContext = $rac;
}
$scoping = SAML2_Utils::xpQuery($xml, './saml_protocol:Scoping');
if (!empty($scoping)) {
$scoping =$scoping[0];
if ($scoping->hasAttribute('ProxyCount')) {
$this->ProxyCount = (int)$scoping->getAttribute('ProxyCount');
}
$idpEntries = SAML2_Utils::xpQuery($scoping, './saml_protocol:IDPList/saml_protocol:IDPEntry');
foreach($idpEntries as $idpEntry) {
if (!$idpEntry->hasAttribute('ProviderID')) {
throw new Exception("Could not get ProviderID from Scoping/IDPEntry element in AuthnRequest object");
}
$this->IDPList[] = $idpEntry->getAttribute('ProviderID');
}
$requesterIDs = SAML2_Utils::xpQuery($scoping, './saml_protocol:RequesterID');
foreach ($requesterIDs as $requesterID) {
$this->RequesterID[] = trim($requesterID->textContent);
}
}
$this->extensions = SAML2_XML_samlp_Extensions::getList($xml);
}
/**
* Retrieve the NameIdPolicy.
*
* @see SAML2_AuthnRequest::setNameIdPolicy()
* @return array The NameIdPolicy.
*/
public function getNameIdPolicy() {
return $this->nameIdPolicy;
}
/**
* Set the NameIDPolicy.
*
* This function accepts an array with the following options:
* - 'Format'
* - 'SPNameQualifier'
* - 'AllowCreate'
*
* @param array $nameIdPolicy The NameIDPolicy.
*/
public function setNameIdPolicy(array $nameIdPolicy) {
$this->nameIdPolicy = $nameIdPolicy;
}
/**
* Retrieve the value of the ForceAuthn attribute.
*
* @return bool The ForceAuthn attribute.
*/
public function getForceAuthn() {
return $this->forceAuthn;
}
/**
* Set the value of the ForceAuthn attribute.
*
* @param bool $forceAuthn The ForceAuthn attribute.
*/
public function setForceAuthn($forceAuthn) {
assert('is_bool($forceAuthn)');
$this->forceAuthn = $forceAuthn;
}
/**
* Retrieve the value of the IsPassive attribute.
*
* @return bool The IsPassive attribute.
*/
public function getIsPassive() {
return $this->isPassive;
}
/**
* Set the value of the IsPassive attribute.
*
* @param bool $isPassive The IsPassive attribute.
*/
public function setIsPassive($isPassive) {
assert('is_bool($isPassive)');
$this->isPassive = $isPassive;
}
/**
* This function sets the scoping for the request
* See Core 3.4.1.2 for the definition of scoping
* Currently we only support an IDPList of idpEntries
* and only the required ProviderID in an IDPEntry
* $providerIDs is an array of Entity Identifiers
*
*/
public function setIDPList($IDPList) {
assert('is_array($IDPList)');
$this->IDPList = $IDPList;
}
/**
* This function retrieves the list of providerIDs from this authentication request.
* Currently we only support a list of ipd ientity id's.
* @return The list of idpidentityids from the request
*/
public function getIDPList() {
return $this->IDPList;
}
public function setProxyCount($ProxyCount) {
assert('is_int($ProxyCount)');
$this->ProxyCount = $ProxyCount;
}
public function getProxyCount() {
return $this->ProxyCount;
}
public function setRequesterID(array $RequesterID) {
$this->RequesterID = $RequesterID;
}
public function getRequesterID() {
return $this->RequesterID;
}
/**
* Retrieve the value of the AssertionConsumerServiceURL attribute.
*
* @return string|NULL The AssertionConsumerServiceURL attribute.
*/
public function getAssertionConsumerServiceURL() {
return $this->assertionConsumerServiceURL;
}
/**
* Set the value of the AssertionConsumerServiceURL attribute.
*
* @param string|NULL $assertionConsumerServiceURL The AssertionConsumerServiceURL attribute.
*/
public function setAssertionConsumerServiceURL($assertionConsumerServiceURL) {
assert('is_string($assertionConsumerServiceURL) || is_null($assertionConsumerServiceURL)');
$this->assertionConsumerServiceURL = $assertionConsumerServiceURL;
}
/**
* Retrieve the value of the ProtocolBinding attribute.
*
* @return string|NULL The ProtocolBinding attribute.
*/
public function getProtocolBinding() {
return $this->protocolBinding;
}
/**
* Set the value of the ProtocolBinding attribute.
*
* @param string $protocolBinding The ProtocolBinding attribute.
*/
public function setProtocolBinding($protocolBinding) {
assert('is_string($protocolBinding) || is_null($protocolBinding)');
$this->protocolBinding = $protocolBinding;
}
/**
* Retrieve the value of the AssertionConsumerServiceIndex attribute.
*
* @return int|NULL The AssertionConsumerServiceIndex attribute.
*/
public function getAssertionConsumerServiceIndex() {
return $this->assertionConsumerServiceIndex;
}
/**
* Set the value of the AssertionConsumerServiceIndex attribute.
*
* @param string|NULL $assertionConsumerServiceIndex The AssertionConsumerServiceIndex attribute.
*/
public function setAssertionConsumerServiceIndex($assertionConsumerServiceIndex) {
assert('is_int($assertionConsumerServiceIndex) || is_null($assertionConsumerServiceIndex)');
$this->assertionConsumerServiceIndex = $assertionConsumerServiceIndex;
}
/**
* Retrieve the RequestedAuthnContext.
*
* @return array|NULL The RequestedAuthnContext.
*/
public function getRequestedAuthnContext() {
return $this->requestedAuthnContext;
}
/**
* Set the RequestedAuthnContext.
*
* @param array|NULL $requestedAuthnContext The RequestedAuthnContext.
*/
public function setRequestedAuthnContext($requestedAuthnContext) {
assert('is_array($requestedAuthnContext) || is_null($requestedAuthnContext)');
$this->requestedAuthnContext = $requestedAuthnContext;
}
/**
* Retrieve the Extensions.
*
* @return SAML2_XML_samlp_Extensions.
*/
public function getExtensions() {
return $this->extensions;
}
/**
* Set the Extensions.
*
* @param array|NULL $extensions The Extensions.
*/
public function setExtensions($extensions) {
assert('is_array($extensions) || is_null($extensions)');
$this->extensions = $extensions;
}
/**
* Convert this authentication request to an XML element.
*
* @return DOMElement This authentication request.
*/
public function toUnsignedXML() {
$root = parent::toUnsignedXML();
if ($this->forceAuthn) {
$root->setAttribute('ForceAuthn', 'true');
}
if ($this->isPassive) {
$root->setAttribute('IsPassive', 'true');
}
if ($this->assertionConsumerServiceURL !== NULL) {
$root->setAttribute('AssertionConsumerServiceURL', $this->assertionConsumerServiceURL);
}
if ($this->protocolBinding !== NULL) {
$root->setAttribute('ProtocolBinding', $this->protocolBinding);
}
if (!empty($this->nameIdPolicy)) {
$nameIdPolicy = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'NameIDPolicy');
if (array_key_exists('Format', $this->nameIdPolicy)) {
$nameIdPolicy->setAttribute('Format', $this->nameIdPolicy['Format']);
}
if (array_key_exists('SPNameQualifier', $this->nameIdPolicy)) {
$nameIdPolicy->setAttribute('SPNameQualifier', $this->nameIdPolicy['SPNameQualifier']);
}
if (array_key_exists('AllowCreate', $this->nameIdPolicy) && $this->nameIdPolicy['AllowCreate']) {
$nameIdPolicy->setAttribute('AllowCreate', 'true');
}
$root->appendChild($nameIdPolicy);
}
$rac = $this->requestedAuthnContext;
if (!empty($rac) && !empty($rac['AuthnContextClassRef'])) {
$e = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'RequestedAuthnContext');
$root->appendChild($e);
if (isset($rac['Comparison']) && $rac['Comparison'] !== 'exact') {
$e->setAttribute('Comparison', $rac['Comparison']);
}
foreach ($rac['AuthnContextClassRef'] as $accr) {
SAML2_Utils::addString($e, SAML2_Const::NS_SAML, 'AuthnContextClassRef', $accr);
}
}
if (!empty($this->extensions)) {
SAML2_XML_samlp_Extensions::addList($root, $this->extensions);
}
if ($this->ProxyCount !== null || count($this->IDPList) > 0 || count($this->RequesterID) > 0) {
$scoping = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'Scoping');
if ($this->ProxyCount !== null) {
$scoping->setAttribute('ProxyCount', $this->ProxyCount);
}
if (count($this->IDPList) > 0) {
$idplist = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'IDPList');
foreach ($this->IDPList as $provider) {
$idpEntry = $this->document->createElementNS(SAML2_Const::NS_SAMLP, 'IDPEntry');
$idpEntry->setAttribute('ProviderID', $provider);
$idplist->appendChild($idpEntry);
}
$scoping->appendChild($idplist);
$root->appendChild($scoping);
}
if (count($this->RequesterID) > 0) {
SAML2_Utils::addStrings($scoping, SAML2_Const::NS_SAMLP, 'RequesterID', FALSE, $this->RequesterID);
}
}
return $root;
}
}
?>