passbolt/passbolt_api · error · BadRequestException
The authentication token does not exist or has been deleted.
Error message
The authentication token does not exist or has been deleted.
What it means
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.
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
Defensive patterns
Strategy: try-catch
Validate before calling
if (empty($token) || !preg_match('/^[0-9a-f-]{36}$/i', $token)) {
// malformed/missing token in URL; restart recover flow before calling the endpoint
} Try / catch
try {
// complete SSO recover success flow
} catch (\Cake\Http\Exception\BadRequestException $e) {
if (str_contains($e->getMessage(), 'authentication token does not exist')) {
// token consumed/deleted: restart the recover process and use the new emailed link
}
throw $e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Ajax/Json request not supported.
- The request is invalid.
- Ajax/Json request not supported.
- Ajax/Json request not supported.
- Ajax/Json request not supported.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/5ef1273ba68980b0.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/SsoRecover/src/Controller/Adfs/AdfsRecoverSuccessController.php:54
$this->Authentication->allowUnauthenticated(['ssoRecoverSuccess']);
}
/**
* @return void
*/
public function ssoRecoverSuccess(): void
{
if ($this->request->is('json')) {
throw new BadRequestException(__('Ajax/Json request not supported.'));
}
$this->User->assertNotLoggedIn();
$token = $this->getTokenFromUrlQuery();
try {
(new SsoAuthenticationTokenGetService())->getActiveNotExpiredOrFail($token, SsoState::TYPE_SSO_RECOVER);
} catch (RecordNotFoundException $e) {
throw new BadRequestException(
__('The authentication token does not exist or has been deleted.'),
null,
$e
);
} catch (CustomValidationException $e) {
throw new BadRequestException(
__('The authentication token has been expired.'),
null,
$e
);
}
$this->viewBuilder()
->setTheme('Passbolt/Sso')
->setLayout('default')
->setTemplatePath('success')
->setTemplate('stage3');
}View on GitHub (pinned to 31c1bbc10f)