{"record":{"id":"5ef1273ba68980b0","repo":"passbolt/passbolt_api","slug":"the-authentication-token-does-not-exist-or-has-been-deleted","errorCode":null,"errorMessage":"The authentication token does not exist or has been deleted.","messagePattern":"The authentication token does not exist or has been deleted\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/SsoRecover/src/Controller/Adfs/AdfsRecoverSuccessController.php","lineNumber":54,"sourceCode":"        $this->Authentication->allowUnauthenticated(['ssoRecoverSuccess']);\n    }\n\n    /**\n     * @return void\n     */\n    public function ssoRecoverSuccess(): void\n    {\n        if ($this->request->is('json')) {\n            throw new BadRequestException(__('Ajax/Json request not supported.'));\n        }\n\n        $this->User->assertNotLoggedIn();\n        $token = $this->getTokenFromUrlQuery();\n\n        try {\n            (new SsoAuthenticationTokenGetService())->getActiveNotExpiredOrFail($token, SsoState::TYPE_SSO_RECOVER);\n        } catch (RecordNotFoundException $e) {\n            throw new BadRequestException(\n                __('The authentication token does not exist or has been deleted.'),\n                null,\n                $e\n            );\n        } catch (CustomValidationException $e) {\n            throw new BadRequestException(\n                __('The authentication token has been expired.'),\n                null,\n                $e\n            );\n        }\n\n        $this->viewBuilder()\n            ->setTheme('Passbolt/Sso')\n            ->setLayout('default')\n            ->setTemplatePath('success')\n            ->setTemplate('stage3');\n    }","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/SsoRecover/src/Controller/Adfs/AdfsRecoverSuccessController.php#L36-L72","documentation":"To complete the SSO recover flow the controller looks up the authentication token from the URL query via SsoAuthenticationTokenGetService::getActiveNotExpiredOrFail() restricted to TYPE_SSO_RECOVER. When no matching active, non-expired token row exists, the RecordNotFoundException is converted into this BadRequestException.","triggerScenarios":"Recover-success URL carries a token that is missing from the database, already consumed/deleted, of the wrong type, or the endpoint is called with a fabricated/empty token.","commonSituations":"Reusing an SSO recover link after the flow already completed (token deleted on use); user clicking an old recovery email link after a newer recover request invalidated it; DB cleanup purging expired tokens; tampered URL query parameters.","solutions":["Restart the recover process from the beginning to generate a fresh SSO recover token and new emailed link","Verify the URL contains the correct, untruncated token id from the latest recover email","Check the authentication_tokens table for the token, its type (sso-recover), and active/expiry status","Ensure the user completes the flow promptly — tokens are single-use and expire"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (empty($token) || !preg_match('/^[0-9a-f-]{36}$/i', $token)) {\n    // malformed/missing token in URL; restart recover flow before calling the endpoint\n}","typeGuard":null,"tryCatchPattern":"try {\n    // complete SSO recover success flow\n} catch (\\Cake\\Http\\Exception\\BadRequestException $e) {\n    if (str_contains($e->getMessage(), 'authentication token does not exist')) {\n        // token consumed/deleted: restart the recover process and use the new emailed link\n    }\n    throw $e;\n}","preventionTips":["Use each recover link exactly once — tokens are single-use","Always take the most recent recovery email's link","Avoid sharing or bookmarking recover URLs containing tokens","Complete the flow promptly after receiving the email"],"tags":["sso","recover","token","not-found","bad-request"],"backgroundTag":"record-not-found","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}