diff --git a/core/Controller/ClientFlowLoginV2Controller.php b/core/Controller/ClientFlowLoginV2Controller.php index 27585cbdb7e80..ba78c6d72afaa 100644 --- a/core/Controller/ClientFlowLoginV2Controller.php +++ b/core/Controller/ClientFlowLoginV2Controller.php @@ -157,7 +157,10 @@ public function showAuthPickerPage($user = ''): StandaloneTemplateResponse { * @NoCSRFRequired * @NoSameSiteCookieRequired */ - public function grantPage(string $stateToken): StandaloneTemplateResponse { + public function grantPage(?string $stateToken): StandaloneTemplateResponse { + if ($stateToken === null) { + return $this->stateTokenMissingResponse(); + } if (!$this->isValidStateToken($stateToken)) { return $this->stateTokenForbiddenResponse(); } @@ -189,7 +192,11 @@ public function grantPage(string $stateToken): StandaloneTemplateResponse { /** * @PublicPage */ - public function apptokenRedirect(string $stateToken, string $user, string $password) { + public function apptokenRedirect(?string $stateToken, string $user, string $password) { + if ($stateToken === null) { + return $this->stateTokenMissingResponse(); + } + if (!$this->isValidStateToken($stateToken)) { return $this->stateTokenForbiddenResponse(); } @@ -232,7 +239,10 @@ public function apptokenRedirect(string $stateToken, string $user, string $passw * @NoAdminRequired * @UseSession */ - public function generateAppPassword(string $stateToken): Response { + public function generateAppPassword(?string $stateToken): Response { + if ($stateToken === null) { + return $this->stateTokenMissingResponse(); + } if (!$this->isValidStateToken($stateToken)) { return $this->stateTokenForbiddenResponse(); } @@ -305,6 +315,19 @@ private function isValidStateToken(string $stateToken): bool { return hash_equals($currentToken, $stateToken); } + private function stateTokenMissingResponse(): StandaloneTemplateResponse { + $response = new StandaloneTemplateResponse( + $this->appName, + '403', + [ + 'message' => $this->l10n->t('State token missing'), + ], + 'guest' + ); + $response->setStatus(Http::STATUS_FORBIDDEN); + return $response; + } + private function stateTokenForbiddenResponse(): StandaloneTemplateResponse { $response = new StandaloneTemplateResponse( $this->appName, diff --git a/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php b/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php index 53d5f392ac647..9c6fb8398b38e 100644 --- a/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php +++ b/tests/Core/Controller/ClientFlowLoginV2ControllerTest.php @@ -188,6 +188,12 @@ public function testShowAuthPickerValidLoginToken() { $this->controller->showAuthPickerPage(); } + public function testGrantPageNoStateToken(): void { + $result = $this->controller->grantPage(null); + + $this->assertSame(Http::STATUS_FORBIDDEN, $result->getStatus()); + } + public function testGrantPageInvalidStateToken() { $this->session->method('get') ->willReturnCallback(function ($name) {