passbolt/passbolt_api · error · BadRequestException
The authentication token has been expired.
Error message
The authentication token has been expired.
What it means
Thrown by OAuth2RecoverSuccessController::ssoRecoverSuccess when the SSO recovery authentication token exists but has failed validation because it expired or is no longer active. The underlying CustomValidationException from SsoAuthenticationTokenGetService::getActiveNotExpiredOrFail is wrapped in a BadRequestException with this user-facing message. Passbolt SSO recovery tokens have a short lifetime for security; once expired the recovery flow must be restarted.
Solutions
- Restart the SSO recovery flow from /recover to generate a fresh token
- Complete the success step promptly after the provider redirects back
- Check server timezone/clock (NTP) if tokens seem to expire too early
- Verify no proxy/cache is replaying an old callback URL
Example fix
// before (stale link reuse) GET /sso/recover/success?token=<expired-token> // after GET /recover/start -> new email/link -> GET /sso/recover/success?token=<fresh-token>
Defensive patterns
Strategy: try-catch
Validate before calling
const isLikelyExpired = (expires) => Date.now() > new Date(expires).getTime(); if (isLikelyExpired(token.expires)) await restartRecoverFlow();
Try / catch
try {
await completeSsoRecoverSuccess(token);
} catch (e) {
if (e.message.includes('expired')) await restartRecoverFlow();
else throw e;
} Prevention
- Complete the recovery flow immediately after receiving the link
- Never bookmark or reuse recovery links
- Synchronize server clocks with NTP
- Monitor token TTL vs. typical provider login duration
When it happens
Trigger: User clicks an SSO recover-success link after the sso auth token (TYPE_SSO_RECOVER) has passed its expiry; user delays between the SSO provider callback and the success request; server clock skew makes the token appear expired.
Common situations: User bookmarks the recovery link and revisits it days later; email delivery delay; user completes the SSO provider login slowly and the token TTL lapses before the callback.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The authentication token does not exist.
- The authentication token does not exist or has been deleted.
- The authentication token has been expired.
- The SSO state is invalid. The SSO state is expired.
- Ajax/Json request not supported.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/3f246ee6fd12fd55.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/SsoRecover/src/Controller/OAuth2/OAuth2RecoverSuccessController.php:60
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)