2626use SimpleSAML \SAML11 \XML \saml \AuthenticationStatement ;
2727use SimpleSAML \SAML11 \XML \saml \Conditions ;
2828use SimpleSAML \SAML11 \XML \saml \NameIdentifier ;
29- use SimpleSAML \SAML11 \XML \saml \Subject ;
30- use SimpleSAML \SOAP \XML \env_200305 \Envelope ;
29+ use SimpleSAML \SAML11 \XML \saml \{ConfirmationMethod , Subject , SubjectConfirmation };
30+ use SimpleSAML \SOAP \Constants as SOAP_C ;
31+ use SimpleSAML \SOAP \XML \env_200305 \{Body , Envelope , Header };
3132use SimpleSAML \Utils ;
32- use SimpleSAML \WSSecurity \XML \wsa_200508 \{Action , Address , EndpointReference , MessageID , To };
33+ use SimpleSAML \WSSecurity \XML \wsa_200508 \{Action , Address , EndpointReference , MessageID , RelatesTo , To };
3334use SimpleSAML \WSSecurity \XML \wsp \AppliesTo ;
34- use SimpleSAML \WSSecurity \XML \wsse \{Password , Security , Username , UsernameToken };
35- use SimpleSAML \WSSecurity \XML \wst_200502 \{RequestSecurityToken , RequestSecurityTokenResponse };
35+ use SimpleSAML \WSSecurity \XML \wsse \{KeyIdentifier , Password , Security , SecurityTokenReference , Username , UsernameToken };
36+ use SimpleSAML \WSSecurity \XML \wst_200502 \{KeyType , KeyTypeEnum , Lifetime , RequestType , RequestTypeEnum , TokenType };
37+ use SimpleSAML \WSSecurity \XML \wst_200502 \{RequestedSecurityToken , RequestSecurityToken , RequestSecurityTokenResponse };
38+ use SimpleSAML \WSSecurity \XML \wst_200502 \{RequestedAttachedReference , RequestedUnattachedReference };
39+ use SimpleSAML \WSSecurity \XML \wsu \{Created , Expires , Timestamp };
3640use SimpleSAML \XHTML \Template ;
41+ use SimpleSAML \XML \Attribute as XMLAttribute ;
3742use SimpleSAML \XMLSecurity \Alg \Signature \SignatureAlgorithmFactory ;
3843use SimpleSAML \XMLSecurity \Key \PrivateKey ;
3944use SimpleSAML \XMLSecurity \Key \X509Certificate as PublicKey ;
@@ -124,6 +129,7 @@ public static function receivePassiveAuthnRequest(
124129 $ state = [
125130 'Responder ' => [ADFS ::class, 'sendPassiveResponse ' ],
126131 'SPMetadata ' => $ spMetadata ->toArray (),
132+ 'MessageID ' => $ messageid ->getContent (),
127133 // Dirty hack to leverage the SAML ECP logics
128134 'saml:Binding ' => SAML2_C ::BINDING_PAOS ,
129135 ];
@@ -291,8 +297,6 @@ private static function generatePassiveAssertion(
291297 $ notBefore = DateInterval::createFromDateString ('30 seconds ' );
292298 $ notOnOrAfter = DateInterval::createFromDateString (sprintf ('%d seconds ' , $ assertionLifetime ));
293299 $ assertionID = $ randomUtils ->generateID ();
294- // $nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN';
295- // $nameid = htmlspecialchars($nameid);
296300 $ now = new DateTimeImmutable ('now ' , new DateTimeZone ('Z ' ));
297301
298302 if ($ httpUtils ->isHTTPS ()) {
@@ -312,20 +316,20 @@ private static function generatePassiveAssertion(
312316 );
313317
314318 $ nameIdentifier = new NameIdentifier ($ nameid , null , C::NAMEID_UNSPECIFIED );
315- $ subject = new Subject (null , $ nameIdentifier );
319+ $ subject = new Subject (new SubjectConfirmation ([ new ConfirmationMethod (C:: CM_BEARER )]) , $ nameIdentifier );
316320
317321 $ authenticationStatement = new AuthenticationStatement ($ subject , $ method , $ now );
318322
319323 $ attrs = [];
320324 $ attrs [] = new Attribute (
321325 'UPN ' ,
322326 'http://schemas.xmlsoap.org/claims ' ,
323- $ attributes ['userPrincipalName ' ][0 ],
327+ [ new AttributeValue ( $ attributes ['http://schemas.xmlsoap.org/claims/UPN ' ][0 ]) ],
324328 );
325329 $ attrs [] = new Attribute (
326330 'ImmutableID ' ,
327331 'http://schemas.microsoft.com/LiveID/Federation/2008/05 ' ,
328- $ attributes ['ms-DS-ConsistencyGuid ' ][0 ],
332+ [ new AttributeValue ( $ attributes ['http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID ' ][0 ]) ],
329333 );
330334
331335 $ attributeStatement = new AttributeStatement ($ subject , $ attrs );
@@ -336,7 +340,7 @@ private static function generatePassiveAssertion(
336340 $ now ,
337341 $ conditions ,
338342 null , // Advice
339- [$ authenticationStatement , $ attributeStatement ],
343+ [$ attributeStatement , $ authenticationStatement ],
340344 );
341345 }
342346
@@ -581,10 +585,14 @@ public static function sendPassiveResponse(array $state): void
581585 $ assertionLifetime = $ idpMetadata ->getOptionalInteger ('assertion.lifetime ' , 300 );
582586 }
583587
588+ $ now = new DateTimeImmutable ('now ' , new DateTimeZone ('Z ' ));
589+ $ created = $ now ->sub (DateInterval::createFromDateString (sprintf ('30 seconds ' )));
590+ $ expires = $ now ->add (DateInterval::createFromDateString (sprintf ('%d seconds ' , $ assertionLifetime )));
591+
584592 $ attributes = $ state ['Attributes ' ];
585- $ nameid = $ attributes [ ' ms-DS-ConsistencyGuid ' ][0 ];
593+ $ nameid = $ state [ ' saml:NameID ' ][SAML2_C :: NAMEID_UNSPECIFIED ];
586594
587- $ assertion = ADFS ::generateActiveAssertion ($ idpEntityId , $ spEntityId , $ nameid , $ attributes , $ assertionLifetime );
595+ $ assertion = ADFS ::generatePassiveAssertion ($ idpEntityId , $ spEntityId , $ nameid-> getValue () , $ attributes , $ assertionLifetime );
588596
589597 $ privateKeyCfg = $ idpMetadata ->getOptionalString ('privatekey ' , null );
590598 $ certificateCfg = $ idpMetadata ->getOptionalString ('certificate ' , null );
@@ -603,7 +611,65 @@ public static function sendPassiveResponse(array $state): void
603611 $ assertion = ADFS ::signAssertion ($ assertion , $ privateKeyFile , $ certificateFile , $ algo , $ passphrase );
604612 $ assertion = Assertion::fromXML ($ assertion ->toXML ());
605613 }
606- \SimpleSAML \Logger::debug ($ assertion ->toXML ()->ownerDocument ->saveXML ());
614+
615+ $ requestedSecurityToken = new RequestedSecurityToken ([$ assertion ]);
616+ $ lifetime = new LifeTime (new Created ($ created ), new Expires ($ expires ));
617+ $ appliesTo = new AppliesTo ([new EndpointReference (new Address ($ spEntityId ))]);
618+
619+ $ requestedAttachedReference = new RequestedAttachedReference (
620+ new SecurityTokenReference (null , null , [
621+ new KeyIdentifier (
622+ $ assertion ->getId (),
623+ 'http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID ' ,
624+ ),
625+ ]),
626+ );
627+ $ requestedUnattachedReference = new RequestedUnattachedReference (
628+ new SecurityTokenReference (null , null , [
629+ new KeyIdentifier (
630+ $ assertion ->getId (),
631+ 'http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID ' ,
632+ ),
633+ ]),
634+ );
635+ $ tokenType = new TokenType (C::NS_SAML );
636+ $ requestType = new RequestType ([RequestTypeEnum::Issue]);
637+ $ keyType = new KeyType (['http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey ' ]);
638+
639+ $ requestSecurityTokenResponse = new RequestSecurityTokenResponse (null , [
640+ $ lifetime ,
641+ $ appliesTo ,
642+ $ requestedSecurityToken ,
643+ $ requestedAttachedReference ,
644+ $ requestedUnattachedReference ,
645+ $ tokenType ,
646+ $ requestType ,
647+ $ keyType ,
648+ ]);
649+
650+ // Build envelope
651+ $ mustUnderstand = new XMLAttribute (SOAP_C ::NS_SOAP_ENV_12 , 'env ' , 'mustUnderstand ' , '1 ' );
652+ $ header = new Header ([
653+ new Action ('http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue ' , [$ mustUnderstand ]),
654+ new RelatesTo ($ state ['MessageID ' ], null ),
655+ new Security (
656+ [
657+ new Timestamp (
658+ new Created ($ created ),
659+ new Expires ($ expires ),
660+ ),
661+ ],
662+ [$ mustUnderstand ],
663+ ),
664+ ]);
665+ $ body = new Body (null , [$ requestSecurityTokenResponse ]);
666+ $ envelope = new Envelope ($ body , $ header );
667+
668+ $ xmlResponse = $ envelope ->toXML ();
669+ \SimpleSAML \Logger::debug ($ xmlResponse ->ownerDocument ->saveXML ($ xmlResponse ));
670+
671+ echo $ xmlResponse ->ownerDocument ->saveXML ($ xmlResponse );
672+ exit ();
607673 }
608674
609675
0 commit comments