99use SimpleSAML \Assert \Assert ;
1010use SimpleSAML \SAML2 \{
1111 Binding ,
12+ Constants as C ,
1213 Metadata ,
1314 MetadataProviderInterface ,
1415 StateProviderInterface ,
1516 StorageProviderInterface ,
1617 Utils ,
1718};
1819use SimpleSAML \SAML2 \Binding \HTTPArtifact ;
19- use SimpleSAML \SAML2 \Exception \{MetadataNotFoundException , RemoteException , RuntimeException };
20+ use SimpleSAML \SAML2 \Exception \{
21+ MetadataNotFoundException ,
22+ ProtocolViolationException ,
23+ RemoteException ,
24+ RuntimeException ,
25+ };
2026use SimpleSAML \SAML2 \Exception \Protocol \{RequestDeniedException , ResourceNotRecognizedException };
2127use SimpleSAML \SAML2 \Process \Validator \ResponseValidator ;
2228use SimpleSAML \SAML2 \XML \saml \{
@@ -163,6 +169,18 @@ public function receiveResponse(ServerRequestInterface $request): Response
163169 $ this ->responseWasSigned = $ rawResponse ->isSigned ();
164170 $ verifiedResponse = $ this ->responseWasSigned ? $ this ->verifyElementSignature ($ rawResponse ) : $ rawResponse ;
165171
172+ /**
173+ * 4.1.4.1: The <Issuer> element MAY be omitted, but if present it MUST contain the unique identifier
174+ * of the issuing identity provider; the Format attribute MUST be omitted or have a value of
175+ * urn:oasis:names:tc:SAML:2.0:nameid-format:entity.
176+ */
177+ Assert::nullOrSame (
178+ $ verifiedResponse ->getIssuer ()?->getFormat(),
179+ C::NAMEID_ENTITY ,
180+ ProtocolViolationException::class,
181+ );
182+ $ issuer = $ verifiedResponse ->getIssuer ()?->getContent();
183+
166184 $ state = null ;
167185 $ stateId = $ verifiedResponse ->getInResponseTo ();
168186
@@ -185,7 +203,6 @@ public function receiveResponse(ServerRequestInterface $request): Response
185203 }
186204 }
187205
188- $ issuer = $ verifiedResponse ->getIssuer ()->getContent ();
189206 if ($ state === null ) {
190207 if ($ this ->enableUnsolicited === false ) {
191208 throw new RequestDeniedException ('Unsolicited responses are denied by configuration. ' );
@@ -220,6 +237,17 @@ public function receiveResponse(ServerRequestInterface $request): Response
220237
221238 // Decrypt and verify assertions, then rebuild the response.
222239 $ verifiedAssertions = $ this ->decryptAndVerifyAssertions ($ verifiedResponse ->getAssertions ());
240+
241+ /**
242+ * It MUST contain at least one <Assertion>. Each assertion's <Issuer> element MUST contain the
243+ * unique identifier of the issuing identity provider; the Format attribute MUST be omitted or have a value
244+ * of urn:oasis:names:tc:SAML:2.0:nameid-format:entity.
245+ */
246+ Assert::minCount ($ verifiedAssertions , 1 , ProtocolViolationException::class);
247+ foreach ($ verifiedAssertions ->getIssuer ()->getFormat () as $ format ) {
248+ Assert::nullOrSame ($ format , C::NAMEID_ENTITY , ProtocolViolationException::class);
249+ }
250+
223251 $ decryptedResponse = new Response (
224252 $ verifiedResponse ->getStatus (),
225253 $ verifiedResponse ->getIssueInstant (),
0 commit comments