ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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
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}
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)
setNameIdPolicy(array $nameIdPolicy)
Set the NameIDPolicy.
setProxyCount($ProxyCount)
toUnsignedXML()
Convert this authentication request to an XML element.
parseNameIdPolicy(\DOMElement $xml)
setIDPList(array $IDPList)
This function sets the scoping for the request.
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
$nameId
Definition: saml2-acs.php:138
$root
Definition: sabredav.php:45