diff --git a/src/SPIDAuth.php b/src/SPIDAuth.php index 6c5d128..a296dcd 100644 --- a/src/SPIDAuth.php +++ b/src/SPIDAuth.php @@ -65,7 +65,7 @@ public function doLogin(): RedirectResponse $idp = request('provider'); $this->checkIdp($idp); - $relayState = $this->getRandomRelayState(); + $relayState = $this->getRandomString(); $idpRedirectTo = $this->getSAML($idp)->login($relayState, [], true, false, true); $requestDocument = new DOMDocument(); SAMLUtils::loadXML($requestDocument, $this->getSAML($idp)->getLastRequestXML()); @@ -161,10 +161,11 @@ public function acs(): RedirectResponse $SPIDUser = new SPIDUser($attributes); $idpEntityName = $this->getIdpEntityName($lastResponseXML); + $spidSessionIndex = $this->getSAML($idp)->getSessionIndex() ?? $this->getRandomString(); session(['spid_idp' => $idp]); session(['spid_idpEntityName' => $idpEntityName]); - session(['spid_sessionIndex' => $this->getSAML($idp)->getSessionIndex()]); + session(['spid_sessionIndex' => $spidSessionIndex]); session(['spid_nameId' => $this->getSAML($idp)->getNameId()]); session(['spid_user' => $SPIDUser]); @@ -752,12 +753,12 @@ protected function getIdpEntityName(string $responseXML) } /** - * Return a random string to be used as RelayState value. + * Return a random string. * * @return string random string * @codeCoverageIgnore */ - protected function getRandomRelayState(): string + protected function getRandomString(): string { return Str::random(32); } diff --git a/tests/ResponseValidationTest.php b/tests/ResponseValidationTest.php index d3b6bea..2826720 100644 --- a/tests/ResponseValidationTest.php +++ b/tests/ResponseValidationTest.php @@ -198,7 +198,7 @@ public function testWrongAuthContextClassRef() public function testInvalidResponseIssueInstant() { $this->runValidationTest([ - 'responseXmlFile' => 'valid.xml', + 'responseXmlFile' => 'valid_level1.xml', 'responseIssueInstant' => 'invalid-response-issue-instant', 'exceptionMessage' => 'SAML response validation error: invalid IssueInstant attribute', ]); @@ -207,7 +207,7 @@ public function testInvalidResponseIssueInstant() public function testInvalidAssertionIssueInstant() { $this->runValidationTest([ - 'responseXmlFile' => 'valid.xml', + 'responseXmlFile' => 'valid_level1.xml', 'assertionIssueInstant' => 'invalid-assertion-issue-instant', 'exceptionMessage' => 'SAML response validation error: invalid IssueInstant attribute', ]); @@ -216,13 +216,13 @@ public function testInvalidAssertionIssueInstant() public function testWrongResponseIssueInstant() { $this->runValidationTest([ - 'responseXmlFile' => 'valid.xml', + 'responseXmlFile' => 'valid_level1.xml', 'responseIssueInstant' => SAMLUtils::parseTime2SAML(time() + 400), 'exceptionMessage' => 'SAML response validation error: wrong Response IssueInstant attribute', ]); $this->runValidationTest([ - 'responseXmlFile' => 'valid.xml', + 'responseXmlFile' => 'valid_level1.xml', 'responseIssueInstant' => SAMLUtils::parseTime2SAML(time() - 400), 'exceptionMessage' => 'SAML response validation error: wrong Response IssueInstant attribute', ]); @@ -231,13 +231,13 @@ public function testWrongResponseIssueInstant() public function testWrongAssertionIssueInstant() { $this->runValidationTest([ - 'responseXmlFile' => 'valid.xml', + 'responseXmlFile' => 'valid_level1.xml', 'assertionIssueInstant' => SAMLUtils::parseTime2SAML(time() + 400), 'exceptionMessage' => 'SAML response validation error: wrong Assertion IssueInstant attribute', ]); $this->runValidationTest([ - 'responseXmlFile' => 'valid.xml', + 'responseXmlFile' => 'valid_level1.xml', 'assertionIssueInstant' => SAMLUtils::parseTime2SAML(time() - 400), 'exceptionMessage' => 'SAML response validation error: wrong Assertion IssueInstant attribute', ]); diff --git a/tests/SPIDAuthBaseTestCase.php b/tests/SPIDAuthBaseTestCase.php index 5e65c60..d433cf3 100644 --- a/tests/SPIDAuthBaseTestCase.php +++ b/tests/SPIDAuthBaseTestCase.php @@ -47,10 +47,10 @@ protected function getPackageProviders($app) return ['Italia\SPIDAuth\ServiceProvider']; } - protected function setSPIDAuthMock() + protected function setSPIDAuthMock($spidLevel = 1) { $testRedirectURL = $this->app['config']->get('spid-idps.test.singleSignOnService.url'); - $responseXML = file_get_contents(__DIR__ . '/responses/valid.xml'); + $responseXML = file_get_contents(__DIR__ . "/responses/valid_level{$spidLevel}.xml"); $compiledResponseXML = str_replace('{{IssueInstant}}', SAMLUtils::parseTime2SAML(time()), $responseXML); $compiledResponseXML = str_replace('{{ResponseIssueInstant}}', SAMLUtils::parseTime2SAML(time()), $compiledResponseXML); $compiledResponseXML = str_replace('{{AssertionIssueInstant}}', SAMLUtils::parseTime2SAML(time()), $compiledResponseXML); @@ -79,7 +79,9 @@ protected function setSPIDAuthMock() ' ); $SAMLAuth->shouldReceive('getLastResponseXML')->andReturn($compiledResponseXML)->byDefault(); - $SAMLAuth->shouldReceive('getSessionIndex')->andReturn('sessionIndex'); + $SAMLAuth->shouldReceive('getSessionIndex')->andReturnUsing(function () use ($spidLevel) { + return $spidLevel > 1 ? null : 'sessionIndex'; + }); $SAMLAuth->shouldReceive('getNameId')->andReturn('nameId'); $SAMLAuth->shouldReceive('logout')->with(URL::to($this->afterLogoutURL), [], 'nameId', 'sessionIndex', false, SAMLConstants::NAMEID_TRANSIENT, 'spid-testenv')->andReturn( Response::redirectTo($this->logoutURL) @@ -150,7 +152,7 @@ protected function setSPIDAuthMock() }); $SPIDAuth->shouldReceive('getSAML')->andReturn($SAMLAuth); - $SPIDAuth->shouldReceive('getRandomRelayState')->andReturn('RANDOM_STRING'); + $SPIDAuth->shouldReceive('getRandomString')->andReturn('RANDOM_STRING'); $this->app->instance('SPIDAuth', $SPIDAuth); return $SAMLAuth; diff --git a/tests/SPIDAuthTest.php b/tests/SPIDAuthTest.php index abb08f7..9a1a1e2 100644 --- a/tests/SPIDAuthTest.php +++ b/tests/SPIDAuthTest.php @@ -114,10 +114,11 @@ public function testDoLogin() $response->assertRedirect(); } - public function testAcs() + public function testAcs($spidLevel = 1) { Event::fake(); - $this->setSPIDAuthMock(); + $this->setSPIDAuthMock($spidLevel); + $expectedSessionIndex = $spidLevel > 1 ? 'RANDOM_STRING' : 'sessionIndex'; $response = $this->withCookies([ 'spid_lastRequestId' => 'UNIQUE_ID', @@ -126,7 +127,7 @@ public function testAcs() ])->post($this->acsURL); $response->assertSessionHas('spid_idpEntityName', 'Test IdP'); - $response->assertSessionHas('spid_sessionIndex', 'sessionIndex'); + $response->assertSessionHas('spid_sessionIndex', $expectedSessionIndex); $response->assertSessionHas('spid_nameId', 'nameId'); $response->assertSessionHas('spid_user'); $response->assertRedirect($this->afterLoginURL); @@ -259,6 +260,16 @@ public function testAcsWithReplayAttack() $response->assertStatus(500); } + public function testAcsWithSpidLevel2() + { + $this->testAcs(2); + } + + public function testAcsWithSpidLevel3() + { + $this->testAcs(3); + } + public function testLogout() { $this->testAcs(); diff --git a/tests/responses/empty_audiencerestriction.xml b/tests/responses/empty_audiencerestriction.xml index 4b51b81..d29a0c7 100644 --- a/tests/responses/empty_audiencerestriction.xml +++ b/tests/responses/empty_audiencerestriction.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/empty_conditions.xml b/tests/responses/empty_conditions.xml index 882ac57..7efa176 100644 --- a/tests/responses/empty_conditions.xml +++ b/tests/responses/empty_conditions.xml @@ -30,7 +30,7 @@ NotOnOrAfter="{{NotOnOrAfter}}" /> + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/empty_conditions_notbefore.xml b/tests/responses/empty_conditions_notbefore.xml index 768df81..c38c1de 100644 --- a/tests/responses/empty_conditions_notbefore.xml +++ b/tests/responses/empty_conditions_notbefore.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/empty_conditions_notonorafter.xml b/tests/responses/empty_conditions_notonorafter.xml index 5416127..3c9d3c9 100644 --- a/tests/responses/empty_conditions_notonorafter.xml +++ b/tests/responses/empty_conditions_notonorafter.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/empty_nameid.xml b/tests/responses/empty_nameid.xml index 0dd47d4..6c97b06 100644 --- a/tests/responses/empty_nameid.xml +++ b/tests/responses/empty_nameid.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/empty_subjectconfirmationdata_recipient.xml b/tests/responses/empty_subjectconfirmationdata_recipient.xml index c8844ca..1f0c847 100644 --- a/tests/responses/empty_subjectconfirmationdata_recipient.xml +++ b/tests/responses/empty_subjectconfirmationdata_recipient.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/missing_destination.xml b/tests/responses/missing_destination.xml index 55c9a0e..c500d73 100644 --- a/tests/responses/missing_destination.xml +++ b/tests/responses/missing_destination.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/missing_inresponseto.xml b/tests/responses/missing_inresponseto.xml index 844d250..45cd035 100644 --- a/tests/responses/missing_inresponseto.xml +++ b/tests/responses/missing_inresponseto.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/missing_nameid_namequalifier.xml b/tests/responses/missing_nameid_namequalifier.xml index a5a79e4..4ea66e9 100644 --- a/tests/responses/missing_nameid_namequalifier.xml +++ b/tests/responses/missing_nameid_namequalifier.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/missing_subjectconfirmationdata_inresponseto.xml b/tests/responses/missing_subjectconfirmationdata_inresponseto.xml index 4367915..a99ba5a 100644 --- a/tests/responses/missing_subjectconfirmationdata_inresponseto.xml +++ b/tests/responses/missing_subjectconfirmationdata_inresponseto.xml @@ -33,7 +33,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/valid.xml b/tests/responses/valid_level1.xml similarity index 97% rename from tests/responses/valid.xml rename to tests/responses/valid_level1.xml index 78a5f4b..ac6d85c 100644 --- a/tests/responses/valid.xml +++ b/tests/responses/valid_level1.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/valid_level2.xml b/tests/responses/valid_level2.xml new file mode 100644 index 0000000..c48f620 --- /dev/null +++ b/tests/responses/valid_level2.xml @@ -0,0 +1,45 @@ + + spid-testenv + + + + spid-testenv + + + {{NameID}} + + + + + + + + {{Audience}} + + + + + https://www.spid.gov.it/SpidL2 + + + + {{Attributes}} + + + diff --git a/tests/responses/valid_level3.xml b/tests/responses/valid_level3.xml new file mode 100644 index 0000000..942ba04 --- /dev/null +++ b/tests/responses/valid_level3.xml @@ -0,0 +1,45 @@ + + spid-testenv + + + + spid-testenv + + + {{NameID}} + + + + + + + + {{Audience}} + + + + + https://www.spid.gov.it/SpidL3 + + + + {{Attributes}} + + + diff --git a/tests/responses/wrong_assertion_issuer_format.xml b/tests/responses/wrong_assertion_issuer_format.xml index d05d33b..51a345e 100644 --- a/tests/responses/wrong_assertion_issuer_format.xml +++ b/tests/responses/wrong_assertion_issuer_format.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/wrong_assertion_version.xml b/tests/responses/wrong_assertion_version.xml index c75d519..bafa97b 100644 --- a/tests/responses/wrong_assertion_version.xml +++ b/tests/responses/wrong_assertion_version.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/wrong_authcontextclassref.xml b/tests/responses/wrong_authcontextclassref.xml index 886617f..f813376 100644 --- a/tests/responses/wrong_authcontextclassref.xml +++ b/tests/responses/wrong_authcontextclassref.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> urn:oasis:names:tc:SAML:2.0:ac:classes:SpidL1 diff --git a/tests/responses/wrong_issuer_format.xml b/tests/responses/wrong_issuer_format.xml index 94621a2..fec6704 100644 --- a/tests/responses/wrong_issuer_format.xml +++ b/tests/responses/wrong_issuer_format.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1 diff --git a/tests/responses/wrong_nameid_format.xml b/tests/responses/wrong_nameid_format.xml index 4c875db..888df08 100644 --- a/tests/responses/wrong_nameid_format.xml +++ b/tests/responses/wrong_nameid_format.xml @@ -34,7 +34,7 @@ + SessionIndex="sessionIndex"> https://www.spid.gov.it/SpidL1