diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php index d6f6ef156..a84bd3205 100644 --- a/app/Access/Oidc/OidcService.php +++ b/app/Access/Oidc/OidcService.php @@ -49,6 +49,11 @@ class OidcService $url = $provider->getAuthorizationUrl(); session()->put('oidc_pkce_code', $provider->getPkceCode() ?? ''); + $returnUrl = Theme::dispatch(ThemeEvents::OIDC_AUTH_PRE_REDIRECT, $url); + if (is_string($returnUrl)) { + $url = $returnUrl; + } + return [ 'url' => $url, 'state' => $provider->getState(), diff --git a/app/Theming/ThemeEvents.php b/app/Theming/ThemeEvents.php index c6266b32b..71778ec44 100644 --- a/app/Theming/ThemeEvents.php +++ b/app/Theming/ThemeEvents.php @@ -87,6 +87,17 @@ class ThemeEvents */ const COMMONMARK_ENVIRONMENT_CONFIGURE = 'commonmark_environment_configure'; + /** + * OIDC auth pre-redirect event. + * Runs just before BookStack redirects the user to the identity provider for authentication. + * Provides the redirect URL that will be used. + * If the listener returns a string value, that will be used as the redirect URL instead. + * + * @param string $redirectUrl + * @return string|null + */ + const OIDC_AUTH_PRE_REDIRECT = 'oidc_auth_pre_redirect'; + /** * OIDC ID token pre-validate event. * Runs just before BookStack validates the user ID token data upon login. diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index 710e53757..8508568f1 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -822,6 +822,34 @@ class OidcTest extends TestCase ]); } + public function test_oidc_auth_pre_redirect_theme_event_with_return() + { + $args = []; + $callback = function (...$eventArgs) use (&$args) { + $args = $eventArgs; + return 'https://cats.example.com?beans=true'; + }; + Theme::listen(ThemeEvents::OIDC_AUTH_PRE_REDIRECT, $callback); + + $resp = $this->post('/oidc/login'); + $resp->assertRedirect('https://cats.example.com?beans=true'); + + $this->assertCount(1, $args); + $this->assertStringStartsWith('https://oidc.local/auth', $args[0]); + } + + public function test_oidc_auth_pre_redirect_theme_event_with_no_return() + { + $callback = function ($redirectUrl) { + $redirectUrl = 'cat'; + }; + Theme::listen(ThemeEvents::OIDC_AUTH_PRE_REDIRECT, $callback); + + $resp = $this->post('/oidc/login'); + $redirect = $resp->headers->get('Location'); + $this->assertStringStartsWith('https://oidc.local/auth?', $redirect); + } + public function test_pkce_used_on_authorize_and_access() { // Start auth