{"record":{"id":"2a9d411453a3cf0c","repo":"passbolt/passbolt_api","slug":"the-authentication-token-does-not-exist-or-has-been-deleted-2a9d41","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":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/SsoRecover/src/Controller/PingOne/PingOneRecoverSuccessController.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/PingOne/PingOneRecoverSuccessController.php#L36-L72","documentation":"Thrown by PingOneRecoverSuccessController::ssoRecoverSuccess when SsoAuthenticationTokenGetService::getActiveNotExpiredOrFail() cannot find an active, non-expired sso_auth_tokens record of type TYPE_SSO_RECOVER matching the token from the URL query. The RecordNotFoundException is wrapped in a BadRequestException with this message.","triggerScenarios":"Token query parameter missing, empty, mistyped, already consumed (single-use), or deleted; token belongs to a different type; recovery flow restarted so old token was replaced.","commonSituations":"User manually edits the callback URL; user completes recovery in one browser then reuses the link elsewhere; token consumed by an earlier duplicate callback request; database cleanup removed stale tokens.","solutions":["Restart the SSO recovery flow to obtain a fresh token link","Verify the token query parameter is present and copied exactly from the email/link","Do not reuse the success URL after the flow completed (token is single-use)","Check sso_auth_tokens table for the token id and its active/expires fields when debugging"],"exampleFix":"// before: reused/consumed token\nGET /sso/recover/success/pingone?token=<already-used>\n// after\nGET /recover/start -> new link -> GET /sso/recover/success/pingone?token=<new-token>","handlingStrategy":"validation","validationCode":"if (!token || typeof token !== 'string' || token.length < 8) {\n  throw new Error('Missing or malformed SSO recover token in URL.');\n}","typeGuard":"const hasToken = (q) => typeof q.token === 'string' && q.token.length > 0;","tryCatchPattern":"try {\n  await ssoRecoverSuccess(token);\n} catch (e) {\n  if (e.message.includes('does not exist')) {\n    await restartRecoverFlow();\n  } else throw e;\n}","preventionTips":["Use the token exactly as delivered in the link (no manual retyping)","Treat tokens as single-use; never replay the success URL","Restart the flow rather than debugging a consumed token","Keep one browser/tab per recovery flow"],"tags":["sso","auth-token","record-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"}