ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
AuthnRequest.php
Go to the documentation of this file.
1 <?php
2 
3 namespace SAML2;
4 
9 
15 class AuthnRequest extends Request
16 {
22  private $nameIdPolicy;
23 
29  private $forceAuthn;
30 
31 
37  private $ProviderName;
38 
39 
45  private $isPassive;
46 
52  private $IDPList = array();
53 
59  private $ProxyCount = null;
60 
67  private $RequesterID = array();
68 
75 
76 
83 
84 
91 
98 
99 
110 
114  private $subjectConfirmation = array();
115 
120 
124  private $nameId;
125 
132  public function __construct(\DOMElement $xml = null)
133  {
134  parent::__construct('AuthnRequest', $xml);
135 
136  $this->nameIdPolicy = array();
137  $this->forceAuthn = false;
138  $this->isPassive = false;
139 
140  if ($xml === null) {
141  return;
142  }
143 
144  $this->forceAuthn = Utils::parseBoolean($xml, 'ForceAuthn', false);
145  $this->isPassive = Utils::parseBoolean($xml, 'IsPassive', false);
146 
147  if ($xml->hasAttribute('AssertionConsumerServiceURL')) {
148  $this->assertionConsumerServiceURL = $xml->getAttribute('AssertionConsumerServiceURL');
149  }
150 
151  if ($xml->hasAttribute('ProtocolBinding')) {
152  $this->protocolBinding = $xml->getAttribute('ProtocolBinding');
153  }
154 
155  if ($xml->hasAttribute('AttributeConsumingServiceIndex')) {
156  $this->attributeConsumingServiceIndex = (int) $xml->getAttribute('AttributeConsumingServiceIndex');
157  }
158 
159  if ($xml->hasAttribute('AssertionConsumerServiceIndex')) {
160  $this->assertionConsumerServiceIndex = (int) $xml->getAttribute('AssertionConsumerServiceIndex');
161  }
162 
163  if ($xml->hasAttribute('ProviderName')) {
164  $this->ProviderName = $xml->getAttribute('ProviderName');
165  }
166 
167  $this->parseSubject($xml);
168  $this->parseNameIdPolicy($xml);
169  $this->parseRequestedAuthnContext($xml);
170  $this->parseScoping($xml);
171  }
172 
178  private function parseSubject(\DOMElement $xml)
179  {
180  $subject = Utils::xpQuery($xml, './saml_assertion:Subject');
181  if (empty($subject)) {
182  return;
183  }
184 
185  if (count($subject) > 1) {
186  throw new \Exception('More than one <saml:Subject> in <saml:AuthnRequest>.');
187  }
188  $subject = $subject[0];
189 
190  $nameId = Utils::xpQuery(
191  $subject,
192  './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData'
193  );
194  if (empty($nameId)) {
195  throw new \Exception('Missing <saml:NameID> or <saml:EncryptedID> in <saml:Subject>.');
196  } elseif (count($nameId) > 1) {
197  throw new \Exception('More than one <saml:NameID> or <saml:EncryptedID> in <saml:Subject>.');
198  }
199  $nameId = $nameId[0];
200  if ($nameId->localName === 'EncryptedData') {
201  /* The NameID element is encrypted. */
202  $this->encryptedNameId = $nameId;
203  } else {
204  $this->nameId = new XML\saml\NameID($nameId);
205  }
206 
207  $subjectConfirmation = Utils::xpQuery($subject, './saml_assertion:SubjectConfirmation');
208  foreach ($subjectConfirmation as $sc) {
209  $this->subjectConfirmation[] = new SubjectConfirmation($sc);
210  }
211  }
212 
218  protected function parseNameIdPolicy(\DOMElement $xml)
219  {
220  $nameIdPolicy = Utils::xpQuery($xml, './saml_protocol:NameIDPolicy');
221  if (empty($nameIdPolicy)) {
222  return;
223  }
224 
225  $nameIdPolicy = $nameIdPolicy[0];
226  if ($nameIdPolicy->hasAttribute('Format')) {
227  $this->nameIdPolicy['Format'] = $nameIdPolicy->getAttribute('Format');
228  }
229  if ($nameIdPolicy->hasAttribute('SPNameQualifier')) {
230  $this->nameIdPolicy['SPNameQualifier'] = $nameIdPolicy->getAttribute('SPNameQualifier');
231  }
232  if ($nameIdPolicy->hasAttribute('AllowCreate')) {
233  $this->nameIdPolicy['AllowCreate'] = Utils::parseBoolean($nameIdPolicy, 'AllowCreate', false);
234  }
235  }
236 
241  {
242  $requestedAuthnContext = Utils::xpQuery($xml, './saml_protocol:RequestedAuthnContext');
243  if (empty($requestedAuthnContext)) {
244  return;
245  }
246 
247  $requestedAuthnContext = $requestedAuthnContext[0];
248 
249  $rac = array(
250  'AuthnContextClassRef' => array(),
251  'Comparison' => Constants::COMPARISON_EXACT,
252  );
253 
254  $accr = Utils::xpQuery($requestedAuthnContext, './saml_assertion:AuthnContextClassRef');
255  foreach ($accr as $i) {
256  $rac['AuthnContextClassRef'][] = trim($i->textContent);
257  }
258 
259  if ($requestedAuthnContext->hasAttribute('Comparison')) {
260  $rac['Comparison'] = $requestedAuthnContext->getAttribute('Comparison');
261  }
262 
263  $this->requestedAuthnContext = $rac;
264  }
265 
271  protected function parseScoping(\DOMElement $xml)
272  {
273  $scoping = Utils::xpQuery($xml, './saml_protocol:Scoping');
274  if (empty($scoping)) {
275  return;
276  }
277 
278  $scoping = $scoping[0];
279 
280  if ($scoping->hasAttribute('ProxyCount')) {
281  $this->ProxyCount = (int) $scoping->getAttribute('ProxyCount');
282  }
283  $idpEntries = Utils::xpQuery($scoping, './saml_protocol:IDPList/saml_protocol:IDPEntry');
284 
285  foreach ($idpEntries as $idpEntry) {
286  if (!$idpEntry->hasAttribute('ProviderID')) {
287  throw new \Exception("Could not get ProviderID from Scoping/IDPEntry element in AuthnRequest object");
288  }
289  $this->IDPList[] = $idpEntry->getAttribute('ProviderID');
290  }
291 
292  $requesterIDs = Utils::xpQuery($scoping, './saml_protocol:RequesterID');
293  foreach ($requesterIDs as $requesterID) {
294  $this->RequesterID[] = trim($requesterID->textContent);
295  }
296  }
297 
304  public function getNameIdPolicy()
305  {
306  return $this->nameIdPolicy;
307  }
308 
309 
320  public function setNameIdPolicy(array $nameIdPolicy)
321  {
322  if (isset($nameIdPolicy['Format']) && !is_string($nameIdPolicy['Format'])) {
323  throw InvalidArgumentException::invalidType('string', $nameIdPolicy['Format']);
324  }
325  if (isset($nameIdPolicy['SPNameQualifier']) && !is_string($nameIdPolicy['SPNameQualifier'])) {
326  throw InvalidArgumentException::invalidType('string', $nameIdPolicy['SPNameQualifier']);
327  }
328  if (isset($nameIdPolicy['AllowCreate']) && !is_bool($nameIdPolicy['AllowCreate'])) {
329  throw InvalidArgumentException::invalidType('bool', $nameIdPolicy['AllowCreate']);
330  }
331 
332  $this->nameIdPolicy = $nameIdPolicy;
333  }
334 
335 
341  public function getForceAuthn()
342  {
343  return $this->forceAuthn;
344  }
345 
346 
352  public function setForceAuthn($forceAuthn)
353  {
354  assert(is_bool($forceAuthn));
355 
356  $this->forceAuthn = $forceAuthn;
357  }
358 
359 
365  public function getProviderName()
366  {
367  return $this->ProviderName;
368  }
369 
370 
376  public function setProviderName($ProviderName)
377  {
378  assert(is_string($ProviderName));
379 
380  $this->ProviderName = $ProviderName;
381  }
382 
383 
389  public function getIsPassive()
390  {
391  return $this->isPassive;
392  }
393 
394 
400  public function setIsPassive($isPassive)
401  {
402  assert(is_bool($isPassive));
403 
404  $this->isPassive = $isPassive;
405  }
406 
407 
423  public function setIDPList(array $IDPList)
424  {
425  $this->IDPList = $IDPList;
426  }
427 
428 
434  public function getIDPList()
435  {
436  return $this->IDPList;
437  }
438 
442  public function setProxyCount($ProxyCount)
443  {
444  assert(is_int($ProxyCount));
445  $this->ProxyCount = $ProxyCount;
446  }
447 
451  public function getProxyCount()
452  {
453  return $this->ProxyCount;
454  }
455 
459  public function setRequesterID(array $RequesterID)
460  {
461  $this->RequesterID = $RequesterID;
462  }
463 
467  public function getRequesterID()
468  {
469  return $this->RequesterID;
470  }
471 
478  {
479  return $this->assertionConsumerServiceURL;
480  }
481 
487  public function setAssertionConsumerServiceURL($assertionConsumerServiceURL)
488  {
489  assert(is_string($assertionConsumerServiceURL) || is_null($assertionConsumerServiceURL));
490 
491  $this->assertionConsumerServiceURL = $assertionConsumerServiceURL;
492  }
493 
499  public function getProtocolBinding()
500  {
501  return $this->protocolBinding;
502  }
503 
509  public function setProtocolBinding($protocolBinding)
510  {
511  assert(is_string($protocolBinding) || is_null($protocolBinding));
512 
513  $this->protocolBinding = $protocolBinding;
514  }
515 
522  {
523  return $this->attributeConsumingServiceIndex;
524  }
525 
531  public function setAttributeConsumingServiceIndex($attributeConsumingServiceIndex)
532  {
533  assert(is_int($attributeConsumingServiceIndex) || is_null($attributeConsumingServiceIndex));
534 
535  $this->attributeConsumingServiceIndex = $attributeConsumingServiceIndex;
536  }
537 
544  {
545  return $this->assertionConsumerServiceIndex;
546  }
547 
553  public function setAssertionConsumerServiceIndex($assertionConsumerServiceIndex)
554  {
555  assert(is_int($assertionConsumerServiceIndex) || is_null($assertionConsumerServiceIndex));
556 
557  $this->assertionConsumerServiceIndex = $assertionConsumerServiceIndex;
558  }
559 
565  public function getRequestedAuthnContext()
566  {
567  return $this->requestedAuthnContext;
568  }
569 
575  public function setRequestedAuthnContext($requestedAuthnContext)
576  {
577  assert(is_array($requestedAuthnContext) || is_null($requestedAuthnContext));
578 
579  $this->requestedAuthnContext = $requestedAuthnContext;
580  }
581 
588  public function getNameId()
589  {
590  if ($this->encryptedNameId !== null) {
591  throw new \Exception('Attempted to retrieve encrypted NameID without decrypting it first.');
592  }
593 
594  return $this->nameId;
595  }
596 
602  public function setNameId($nameId)
603  {
604  assert(is_array($nameId) || is_null($nameId) || $nameId instanceof XML\saml\NameID);
605 
606  if (is_array($nameId)) {
607  $nameId = XML\saml\NameID::fromArray($nameId);
608  }
609  $this->nameId = $nameId;
610  }
611 
618  {
619  /* First create a XML representation of the NameID. */
620  $doc = new \DOMDocument();
621  $root = $doc->createElement('root');
622  $doc->appendChild($root);
623  $this->nameId->toXML($root);
624  $nameId = $root->firstChild;
625 
626  Utils::getContainer()->debugMessage($nameId, 'encrypt');
627 
628  /* Encrypt the NameID. */
629  $enc = new XMLSecEnc();
630  $enc->setNode($nameId);
631  // @codingStandardsIgnoreStart
632  $enc->type = XMLSecEnc::Element;
633  // @codingStandardsIgnoreEnd
634 
635  $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC);
636  $symmetricKey->generateSessionKey();
637  $enc->encryptKey($key, $symmetricKey);
638 
639  $this->encryptedNameId = $enc->encryptNode($symmetricKey);
640  $this->nameId = null;
641  }
642 
649  public function decryptNameId(XMLSecurityKey $key, array $blacklist = array())
650  {
651  if ($this->encryptedNameId === null) {
652  /* No NameID to decrypt. */
653  return;
654  }
655 
656  $nameId = Utils::decryptElement($this->encryptedNameId, $key, $blacklist);
657  Utils::getContainer()->debugMessage($nameId, 'decrypt');
658  $this->nameId = new XML\saml\NameID($nameId);
659 
660  $this->encryptedNameId = null;
661  }
662 
668  public function getSubjectConfirmation()
669  {
670  return $this->subjectConfirmation;
671  }
672 
678  public function setSubjectConfirmation(array $subjectConfirmation)
679  {
680  $this->subjectConfirmation = $subjectConfirmation;
681  }
682 
688  public function toUnsignedXML()
689  {
690  $root = parent::toUnsignedXML();
691 
692  if ($this->forceAuthn) {
693  $root->setAttribute('ForceAuthn', 'true');
694  }
695 
696  if ($this->ProviderName !== null) {
697  $root->setAttribute('ProviderName', $this->ProviderName);
698  }
699 
700  if ($this->isPassive) {
701  $root->setAttribute('IsPassive', 'true');
702  }
703 
704  if ($this->assertionConsumerServiceIndex !== null) {
705  $root->setAttribute('AssertionConsumerServiceIndex', $this->assertionConsumerServiceIndex);
706  } else {
707  if ($this->assertionConsumerServiceURL !== null) {
708  $root->setAttribute('AssertionConsumerServiceURL', $this->assertionConsumerServiceURL);
709  }
710  if ($this->protocolBinding !== null) {
711  $root->setAttribute('ProtocolBinding', $this->protocolBinding);
712  }
713  }
714 
715  if ($this->attributeConsumingServiceIndex !== null) {
716  $root->setAttribute('AttributeConsumingServiceIndex', $this->attributeConsumingServiceIndex);
717  }
718 
719  $this->addSubject($root);
720 
721  if (!empty($this->nameIdPolicy)) {
722  $nameIdPolicy = $this->document->createElementNS(Constants::NS_SAMLP, 'NameIDPolicy');
723  if (array_key_exists('Format', $this->nameIdPolicy)) {
724  $nameIdPolicy->setAttribute('Format', $this->nameIdPolicy['Format']);
725  }
726  if (array_key_exists('SPNameQualifier', $this->nameIdPolicy)) {
727  $nameIdPolicy->setAttribute('SPNameQualifier', $this->nameIdPolicy['SPNameQualifier']);
728  }
729  if (array_key_exists('AllowCreate', $this->nameIdPolicy)) {
730  $nameIdPolicy->setAttribute('AllowCreate', ($this->nameIdPolicy['AllowCreate']) ? 'true' : 'false');
731  }
732  $root->appendChild($nameIdPolicy);
733  }
734 
735  $rac = $this->requestedAuthnContext;
736  if (!empty($rac) && !empty($rac['AuthnContextClassRef'])) {
737  $e = $this->document->createElementNS(Constants::NS_SAMLP, 'RequestedAuthnContext');
738  $root->appendChild($e);
739  if (isset($rac['Comparison']) && $rac['Comparison'] !== Constants::COMPARISON_EXACT) {
740  $e->setAttribute('Comparison', $rac['Comparison']);
741  }
742  foreach ($rac['AuthnContextClassRef'] as $accr) {
743  Utils::addString($e, Constants::NS_SAML, 'AuthnContextClassRef', $accr);
744  }
745  }
746 
747  if ($this->ProxyCount !== null || count($this->IDPList) > 0 || count($this->RequesterID) > 0) {
748  $scoping = $this->document->createElementNS(Constants::NS_SAMLP, 'Scoping');
749  $root->appendChild($scoping);
750  if ($this->ProxyCount !== null) {
751  $scoping->setAttribute('ProxyCount', $this->ProxyCount);
752  }
753  if (count($this->IDPList) > 0) {
754  $idplist = $this->document->createElementNS(Constants::NS_SAMLP, 'IDPList');
755  foreach ($this->IDPList as $provider) {
756  $idpEntry = $this->document->createElementNS(Constants::NS_SAMLP, 'IDPEntry');
757  if (is_string($provider)) {
758  $idpEntry->setAttribute('ProviderID', $provider);
759  } elseif (is_array($provider)) {
760  foreach ($provider as $attribute => $value) {
761  if (in_array($attribute, array(
762  'ProviderID',
763  'Loc',
764  'Name'
765  ), true)) {
766  $idpEntry->setAttribute($attribute, $value);
767  }
768  }
769  }
770  $idplist->appendChild($idpEntry);
771  }
772  $scoping->appendChild($idplist);
773  }
774  if (count($this->RequesterID) > 0) {
775  Utils::addStrings($scoping, Constants::NS_SAMLP, 'RequesterID', false, $this->RequesterID);
776  }
777  }
778 
779  return $root;
780  }
781 
787  private function addSubject(\DOMElement $root)
788  {
789  // If there is no nameId (encrypted or not) there is nothing to create a subject for
790  if ($this->nameId === null && $this->encryptedNameId === null) {
791  return;
792  }
793 
794  $subject = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:Subject');
795  $root->appendChild($subject);
796 
797  if ($this->encryptedNameId === null) {
798  $this->nameId->toXML($subject);
799  } else {
800  $eid = $subject->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:EncryptedID');
801  $eid->appendChild($subject->ownerDocument->importNode($this->encryptedNameId, true));
802  $subject->appendChild($eid);
803  }
804 
805  foreach ($this->subjectConfirmation as $sc) {
806  $sc->toXML($subject);
807  }
808  }
809 }
getIDPList()
This function retrieves the list of providerIDs from this authentication request. ...
parseRequestedAuthnContext(\DOMElement $xml)
setNameIdPolicy(array $nameIdPolicy)
Set the NameIDPolicy.
setProtocolBinding($protocolBinding)
Set the value of the ProtocolBinding attribute.
setAssertionConsumerServiceIndex($assertionConsumerServiceIndex)
Set the value of the AssertionConsumerServiceIndex attribute.
setIDPList(array $IDPList)
This function sets the scoping for the request.
getNameId()
Retrieve the NameId of the subject in the assertion.
__construct(\DOMElement $xml=null)
Constructor for SAML 2 authentication request messages.
setProviderName($ProviderName)
Set the value of the ProviderName attribute.
setNameId($nameId)
Set the NameId of the subject in the assertion.
getRequestedAuthnContext()
Retrieve the RequestedAuthnContext.
setIsPassive($isPassive)
Set the value of the IsPassive attribute.
getAttributeConsumingServiceIndex()
Retrieve the value of the AttributeConsumingServiceIndex attribute.
$nameId
Definition: saml2-acs.php:138
getNameIdPolicy()
Retrieve the NameIdPolicy.
parseSubject(\DOMElement $xml)
addSubject(\DOMElement $root)
Add a Subject-node to the assertion.
getSubjectConfirmation()
Retrieve the SubjectConfirmation elements we have in our Subject element.
encryptNameId(XMLSecurityKey $key)
Encrypt the NameID in the AuthnRequest.
setProxyCount($ProxyCount)
setAssertionConsumerServiceURL($assertionConsumerServiceURL)
Set the value of the AssertionConsumerServiceURL attribute.
getAssertionConsumerServiceIndex()
Retrieve the value of the AssertionConsumerServiceIndex attribute.
getProtocolBinding()
Retrieve the value of the ProtocolBinding attribute.
toUnsignedXML()
Convert this authentication request to an XML element.
$root
Definition: sabredav.php:45
setRequestedAuthnContext($requestedAuthnContext)
Set the RequestedAuthnContext.
getForceAuthn()
Retrieve the value of the ForceAuthn attribute.
parseNameIdPolicy(\DOMElement $xml)
getIsPassive()
Retrieve the value of the IsPassive attribute.
decryptNameId(XMLSecurityKey $key, array $blacklist=array())
Decrypt the NameId of the subject in the assertion.
parseScoping(\DOMElement $xml)
$i
Definition: disco.tpl.php:19
setSubjectConfirmation(array $subjectConfirmation)
Set the SubjectConfirmation elements that should be included in the assertion.
setRequesterID(array $RequesterID)
getProviderName()
Retrieve the value of the ProviderName attribute.
setForceAuthn($forceAuthn)
Set the value of the ForceAuthn attribute.
setAttributeConsumingServiceIndex($attributeConsumingServiceIndex)
Set the value of the AttributeConsumingServiceIndex attribute.
getAssertionConsumerServiceURL()
Retrieve the value of the AssertionConsumerServiceURL attribute.
$key
Definition: croninfo.php:18