diff --git a/CHANGELOG.md b/CHANGELOG.md index f1ff8db9..3cde3a9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ -# Next release +# UNRELEASED * Upgrade the runtime and build toolchain to PHP 8.5 and Node.js 24. * Refresh the CI Docker base image plus Composer and npm dependencies for the PHP 8.5 build. +* Preserve the originally requested deeplink after SAML login instead of redirecting to the homepage #325 # 4.1.4 * Update saml2 library. diff --git a/config/services.yaml b/config/services.yaml index 37aa313e..55da17f5 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -32,6 +32,14 @@ services: surfnet_saml.saml_provider: class: OpenConext\ProfileBundle\Security\Authentication\Provider\SamlProvider + Surfnet\SamlBundle\Security\Authentication\Handler\SuccessHandler: + arguments: + - '@security.http_utils' + - [] + - '@logger' + calls: + - setFirewallName: [ 'saml_based' ] + Psr\Log\LoggerInterface: alias: 'monolog.logger' public: true diff --git a/src/OpenConext/ProfileBundle/Tests/Security/SamlAuthenticationSuccessHandlerTest.php b/src/OpenConext/ProfileBundle/Tests/Security/SamlAuthenticationSuccessHandlerTest.php new file mode 100644 index 00000000..f1e6861f --- /dev/null +++ b/src/OpenConext/ProfileBundle/Tests/Security/SamlAuthenticationSuccessHandlerTest.php @@ -0,0 +1,89 @@ +get(SuccessHandler::class); + + $this->assertSame('saml_based', $successHandler->getFirewallName()); + } + + public function test_a_deeplink_stored_before_login_is_used_as_the_post_login_redirect_target(): void + { + self::bootKernel(); + + $deepLink = 'https://profile.surfconext.nl/attribute-support'; + + $session = new Session(new MockArraySessionStorage()); + $session->set('_security.saml_based.target_path', $deepLink); + + $request = Request::create('https://profile.surfconext.nl/saml/acs', 'POST'); + $request->setSession($session); + + /** @var SuccessHandler $successHandler */ + $successHandler = self::getContainer()->get(SuccessHandler::class); + + $token = $this->createMock(TokenInterface::class); + + $response = $successHandler->onAuthenticationSuccess($request, $token); + + $this->assertNotNull($response); + $this->assertTrue($response->isRedirect($deepLink)); + } + + public function test_without_a_stored_deeplink_the_default_target_path_is_used(): void + { + self::bootKernel(); + + $session = new Session(new MockArraySessionStorage()); + + $request = Request::create('https://profile.surfconext.nl/saml/acs', 'POST'); + $request->setSession($session); + + /** @var SuccessHandler $successHandler */ + $successHandler = self::getContainer()->get(SuccessHandler::class); + + $token = $this->createMock(TokenInterface::class); + + $response = $successHandler->onAuthenticationSuccess($request, $token); + + $this->assertNotNull($response); + $this->assertTrue($response->isRedirect('https://profile.surfconext.nl/')); + } +}