ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 
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 }
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.
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.
$forceAuthn
Definition: login.php:17
getRequestedAuthnContext()
Retrieve the RequestedAuthnContext.
setIsPassive($isPassive)
Set the value of the IsPassive attribute.
$isPassive
Definition: login.php:18
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.
$xml
Definition: metadata.php:240
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.
setRequestedAuthnContext($requestedAuthnContext)
Set the RequestedAuthnContext.
Create styles array
The data for the language used.
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.
setIDPList($IDPList)
This function sets the scoping for the request.
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