ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
AuthnRequest.php
Go to the documentation of this file.
1<?php
2
3namespace SAML2;
4
9
15class AuthnRequest extends Request
16{
23
29 private $forceAuthn;
30
31
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
240 protected function parseRequestedAuthnContext(\DOMElement $xml)
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
421 public function setIDPList($IDPList)
422 {
423 assert(is_array($IDPList));
424 $this->IDPList = $IDPList;
425 }
426
427
433 public function getIDPList()
434 {
435 return $this->IDPList;
436 }
437
441 public function setProxyCount($ProxyCount)
442 {
443 assert(is_int($ProxyCount));
444 $this->ProxyCount = $ProxyCount;
445 }
446
450 public function getProxyCount()
451 {
452 return $this->ProxyCount;
453 }
454
458 public function setRequesterID(array $RequesterID)
459 {
460 $this->RequesterID = $RequesterID;
461 }
462
466 public function getRequesterID()
467 {
468 return $this->RequesterID;
469 }
470
477 {
478 return $this->assertionConsumerServiceURL;
479 }
480
486 public function setAssertionConsumerServiceURL($assertionConsumerServiceURL)
487 {
488 assert(is_string($assertionConsumerServiceURL) || is_null($assertionConsumerServiceURL));
489
490 $this->assertionConsumerServiceURL = $assertionConsumerServiceURL;
491 }
492
498 public function getProtocolBinding()
499 {
500 return $this->protocolBinding;
501 }
502
508 public function setProtocolBinding($protocolBinding)
509 {
510 assert(is_string($protocolBinding) || is_null($protocolBinding));
511
512 $this->protocolBinding = $protocolBinding;
513 }
514
521 {
522 return $this->attributeConsumingServiceIndex;
523 }
524
530 public function setAttributeConsumingServiceIndex($attributeConsumingServiceIndex)
531 {
532 assert(is_int($attributeConsumingServiceIndex) || is_null($attributeConsumingServiceIndex));
533
534 $this->attributeConsumingServiceIndex = $attributeConsumingServiceIndex;
535 }
536
543 {
544 return $this->assertionConsumerServiceIndex;
545 }
546
552 public function setAssertionConsumerServiceIndex($assertionConsumerServiceIndex)
553 {
554 assert(is_int($assertionConsumerServiceIndex) || is_null($assertionConsumerServiceIndex));
555
556 $this->assertionConsumerServiceIndex = $assertionConsumerServiceIndex;
557 }
558
564 public function getRequestedAuthnContext()
565 {
566 return $this->requestedAuthnContext;
567 }
568
574 public function setRequestedAuthnContext($requestedAuthnContext)
575 {
576 assert(is_array($requestedAuthnContext) || is_null($requestedAuthnContext));
577
578 $this->requestedAuthnContext = $requestedAuthnContext;
579 }
580
587 public function getNameId()
588 {
589 if ($this->encryptedNameId !== null) {
590 throw new \Exception('Attempted to retrieve encrypted NameID without decrypting it first.');
591 }
592
593 return $this->nameId;
594 }
595
601 public function setNameId($nameId)
602 {
603 assert(is_array($nameId) || is_null($nameId) || $nameId instanceof XML\saml\NameID);
604
605 if (is_array($nameId)) {
606 $nameId = XML\saml\NameID::fromArray($nameId);
607 }
608 $this->nameId = $nameId;
609 }
610
617 {
618 /* First create a XML representation of the NameID. */
619 $doc = new \DOMDocument();
620 $root = $doc->createElement('root');
621 $doc->appendChild($root);
622 $this->nameId->toXML($root);
623 $nameId = $root->firstChild;
624
625 Utils::getContainer()->debugMessage($nameId, 'encrypt');
626
627 /* Encrypt the NameID. */
628 $enc = new XMLSecEnc();
629 $enc->setNode($nameId);
630 // @codingStandardsIgnoreStart
631 $enc->type = XMLSecEnc::Element;
632 // @codingStandardsIgnoreEnd
633
634 $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC);
635 $symmetricKey->generateSessionKey();
636 $enc->encryptKey($key, $symmetricKey);
637
638 $this->encryptedNameId = $enc->encryptNode($symmetricKey);
639 $this->nameId = null;
640 }
641
648 public function decryptNameId(XMLSecurityKey $key, array $blacklist = array())
649 {
650 if ($this->encryptedNameId === null) {
651 /* No NameID to decrypt. */
652 return;
653 }
654
655 $nameId = Utils::decryptElement($this->encryptedNameId, $key, $blacklist);
656 Utils::getContainer()->debugMessage($nameId, 'decrypt');
657 $this->nameId = new XML\saml\NameID($nameId);
658
659 $this->encryptedNameId = null;
660 }
661
667 public function getSubjectConfirmation()
668 {
669 return $this->subjectConfirmation;
670 }
671
677 public function setSubjectConfirmation(array $subjectConfirmation)
678 {
679 $this->subjectConfirmation = $subjectConfirmation;
680 }
681
687 public function toUnsignedXML()
688 {
689 $root = parent::toUnsignedXML();
690
691 if ($this->forceAuthn) {
692 $root->setAttribute('ForceAuthn', 'true');
693 }
694
695 if ($this->ProviderName !== null) {
696 $root->setAttribute('ProviderName', $this->ProviderName);
697 }
698
699 if ($this->isPassive) {
700 $root->setAttribute('IsPassive', 'true');
701 }
702
703 if ($this->assertionConsumerServiceIndex !== null) {
704 $root->setAttribute('AssertionConsumerServiceIndex', $this->assertionConsumerServiceIndex);
705 } else {
706 if ($this->assertionConsumerServiceURL !== null) {
707 $root->setAttribute('AssertionConsumerServiceURL', $this->assertionConsumerServiceURL);
708 }
709 if ($this->protocolBinding !== null) {
710 $root->setAttribute('ProtocolBinding', $this->protocolBinding);
711 }
712 }
713
714 if ($this->attributeConsumingServiceIndex !== null) {
715 $root->setAttribute('AttributeConsumingServiceIndex', $this->attributeConsumingServiceIndex);
716 }
717
718 $this->addSubject($root);
719
720 if (!empty($this->nameIdPolicy)) {
721 $nameIdPolicy = $this->document->createElementNS(Constants::NS_SAMLP, 'NameIDPolicy');
722 if (array_key_exists('Format', $this->nameIdPolicy)) {
723 $nameIdPolicy->setAttribute('Format', $this->nameIdPolicy['Format']);
724 }
725 if (array_key_exists('SPNameQualifier', $this->nameIdPolicy)) {
726 $nameIdPolicy->setAttribute('SPNameQualifier', $this->nameIdPolicy['SPNameQualifier']);
727 }
728 if (array_key_exists('AllowCreate', $this->nameIdPolicy)) {
729 $nameIdPolicy->setAttribute('AllowCreate', ($this->nameIdPolicy['AllowCreate']) ? 'true' : 'false');
730 }
731 $root->appendChild($nameIdPolicy);
732 }
733
734 $rac = $this->requestedAuthnContext;
735 if (!empty($rac) && !empty($rac['AuthnContextClassRef'])) {
736 $e = $this->document->createElementNS(Constants::NS_SAMLP, 'RequestedAuthnContext');
737 $root->appendChild($e);
738 if (isset($rac['Comparison']) && $rac['Comparison'] !== Constants::COMPARISON_EXACT) {
739 $e->setAttribute('Comparison', $rac['Comparison']);
740 }
741 foreach ($rac['AuthnContextClassRef'] as $accr) {
742 Utils::addString($e, Constants::NS_SAML, 'AuthnContextClassRef', $accr);
743 }
744 }
745
746 if ($this->ProxyCount !== null || count($this->IDPList) > 0 || count($this->RequesterID) > 0) {
747 $scoping = $this->document->createElementNS(Constants::NS_SAMLP, 'Scoping');
748 $root->appendChild($scoping);
749 if ($this->ProxyCount !== null) {
750 $scoping->setAttribute('ProxyCount', $this->ProxyCount);
751 }
752 if (count($this->IDPList) > 0) {
753 $idplist = $this->document->createElementNS(Constants::NS_SAMLP, 'IDPList');
754 foreach ($this->IDPList as $provider) {
755 $idpEntry = $this->document->createElementNS(Constants::NS_SAMLP, 'IDPEntry');
756 if (is_string($provider)) {
757 $idpEntry->setAttribute('ProviderID', $provider);
758 } elseif (is_array($provider)) {
759 foreach ($provider as $attribute => $value) {
760 if (in_array($attribute, array(
761 'ProviderID',
762 'Loc',
763 'Name'
764 ))) {
765 $idpEntry->setAttribute($attribute, $value);
766 }
767 }
768 }
769 $idplist->appendChild($idpEntry);
770 }
771 $scoping->appendChild($idplist);
772 }
773 if (count($this->RequesterID) > 0) {
774 Utils::addStrings($scoping, Constants::NS_SAMLP, 'RequesterID', false, $this->RequesterID);
775 }
776 }
777
778 return $root;
779 }
780
786 private function addSubject(\DOMElement $root)
787 {
788 // If there is no nameId (encrypted or not) there is nothing to create a subject for
789 if ($this->nameId === null && $this->encryptedNameId === null) {
790 return;
791 }
792
793 $subject = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:Subject');
794 $root->appendChild($subject);
795
796 if ($this->encryptedNameId === null) {
797 $this->nameId->toXML($subject);
798 } else {
799 $eid = $subject->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:EncryptedID');
800 $eid->appendChild($subject->ownerDocument->importNode($this->encryptedNameId, true));
801 $subject->appendChild($eid);
802 }
803
804 foreach ($this->subjectConfirmation as $sc) {
805 $sc->toXML($subject);
806 }
807 }
808}
An exception for terminatinating execution or to throw for unit testing.
setForceAuthn($forceAuthn)
Set the value of the ForceAuthn attribute.
getProviderName()
Retrieve the value of the ProviderName attribute.
getIDPList()
This function retrieves the list of providerIDs from this authentication request.
getIsPassive()
Retrieve the value of the IsPassive attribute.
setSubjectConfirmation(array $subjectConfirmation)
Set the SubjectConfirmation elements that should be included in the assertion.
setAssertionConsumerServiceURL($assertionConsumerServiceURL)
Set the value of the AssertionConsumerServiceURL attribute.
getNameIdPolicy()
Retrieve the NameIdPolicy.
parseScoping(\DOMElement $xml)
getForceAuthn()
Retrieve the value of the ForceAuthn attribute.
parseRequestedAuthnContext(\DOMElement $xml)
setRequestedAuthnContext($requestedAuthnContext)
Set the RequestedAuthnContext.
getAssertionConsumerServiceURL()
Retrieve the value of the AssertionConsumerServiceURL attribute.
getProtocolBinding()
Retrieve the value of the ProtocolBinding attribute.
getSubjectConfirmation()
Retrieve the SubjectConfirmation elements we have in our Subject element.
parseSubject(\DOMElement $xml)
getNameId()
Retrieve the NameId of the subject in the assertion.
setIsPassive($isPassive)
Set the value of the IsPassive attribute.
setRequesterID(array $RequesterID)
setIDPList($IDPList)
This function sets the scoping for the request.
setNameIdPolicy(array $nameIdPolicy)
Set the NameIDPolicy.
setProxyCount($ProxyCount)
toUnsignedXML()
Convert this authentication request to an XML element.
parseNameIdPolicy(\DOMElement $xml)
addSubject(\DOMElement $root)
Add a Subject-node to the assertion.
setAssertionConsumerServiceIndex($assertionConsumerServiceIndex)
Set the value of the AssertionConsumerServiceIndex attribute.
encryptNameId(XMLSecurityKey $key)
Encrypt the NameID in the AuthnRequest.
getRequestedAuthnContext()
Retrieve the RequestedAuthnContext.
setNameId($nameId)
Set the NameId of the subject in the assertion.
setProviderName($ProviderName)
Set the value of the ProviderName attribute.
decryptNameId(XMLSecurityKey $key, array $blacklist=array())
Decrypt the NameId of the subject in the assertion.
setProtocolBinding($protocolBinding)
Set the value of the ProtocolBinding attribute.
getAssertionConsumerServiceIndex()
Retrieve the value of the AssertionConsumerServiceIndex attribute.
__construct(\DOMElement $xml=null)
Constructor for SAML 2 authentication request messages.
setAttributeConsumingServiceIndex($attributeConsumingServiceIndex)
Set the value of the AttributeConsumingServiceIndex attribute.
getAttributeConsumingServiceIndex()
Retrieve the value of the AttributeConsumingServiceIndex attribute.
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
$isPassive
Definition: login.php:18
$forceAuthn
Definition: login.php:17
$xml
Definition: metadata.php:240
$nameId
Definition: saml2-acs.php:138