diff --git a/src/Control/Director.php b/src/Control/Director.php index c9d9306411c..98fa0ca5801 100644 --- a/src/Control/Director.php +++ b/src/Control/Director.php @@ -649,7 +649,7 @@ public static function baseURL() // Check if BASE_SCRIPT_URL is defined // e.g. `index.php/` if (defined('BASE_SCRIPT_URL')) { - return $baseURL . BASE_SCRIPT_URL; + return rtrim($baseURL . BASE_SCRIPT_URL, '/') . '/'; } return $baseURL; diff --git a/src/Security/Security.php b/src/Security/Security.php index 7796b065d3d..a32085143a6 100644 --- a/src/Security/Security.php +++ b/src/Security/Security.php @@ -415,7 +415,7 @@ public static function permissionFailure($controller = null, $messageSet = null) $message = $messageSet['default']; $request = $controller->getRequest(); - $requestUrl = '/' . ltrim($request->getURL(true), '/'); + $requestUrl = Director::baseURL() . ltrim($request->getURL(true), '/'); if ($request->hasSession()) { list($messageText, $messageCast) = $parseMessage($message); static::singleton()->setSessionMessage($messageText, ValidationResult::TYPE_WARNING, $messageCast); diff --git a/tests/php/Security/SecurityTest.php b/tests/php/Security/SecurityTest.php index 1ff762df5d0..5c546bf3fdc 100644 --- a/tests/php/Security/SecurityTest.php +++ b/tests/php/Security/SecurityTest.php @@ -78,8 +78,28 @@ protected function tearDown(): void parent::tearDown(); } - public function testAccessingAuthenticatedPageRedirectsToLoginForm() + public static function provideAccessingAuthenticatedPageRedirectsToLoginForm(): array { + return [ + [ + 'baseUrl' => null, + 'expectedBackUrl' => '/SecurityTest_SecuredController', + ], + [ + 'baseUrl' => 'https://www.example.com/subfolder', + 'expectedBackUrl' => '/subfolder/SecurityTest_SecuredController', + ], + ]; + } + + #[DataProvider('provideAccessingAuthenticatedPageRedirectsToLoginForm')] + public function testAccessingAuthenticatedPageRedirectsToLoginForm(?string $baseUrl, string $expectedBackUrl): void + { + if ($baseUrl) { + // We can't set `SS_BASE_URL` because that gets consumed to define the `BASE_URL` constant way before this point. + // Instead set alternate_base_url which at least checks the director logic is being used correctly. + Director::config()->set('alternate_base_url', $baseUrl); + } $this->autoFollowRedirection = false; $response = $this->get('SecurityTest_SecuredController'); @@ -89,6 +109,10 @@ public function testAccessingAuthenticatedPageRedirectsToLoginForm() $response->getHeader('Location') ); + parse_str(parse_url($response->getHeader('Location'), PHP_URL_QUERY), $query); + $this->assertArrayHasKey('BackURL', $query); + $this->assertSame($expectedBackUrl, $query['BackURL']); + $this->logInWithPermission('ADMIN'); $response = $this->get('SecurityTest_SecuredController'); $this->assertEquals(200, $response->getStatusCode());