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

Thrown when the SSO authentication token taken from the URL query cannot be found as an active, non-expired token of type SSO_RECOVER. The underlying SsoAuthenticationTokenGetService::getActiveNotExpiredOrFail raised a RecordNotFoundException (token absent or deleted) which the controller converts to this BadRequestException.

Solutions

  1. Restart the SSO recover flow from the beginning to obtain a fresh token, then use the new link only once.
  2. Verify the URL query token value is complete and unmodified (check for truncation by email clients or redirects).
  3. Check you are on the same passbolt instance/environment that issued the token.
  4. If tokens are being deleted prematurely, inspect cleanup/cron jobs and the sso_authentication_tokens table for the expected record.
Defensive patterns

Strategy: try-catch

Validate before calling

// Client-side: ensure the token query param is present and non-empty before navigating
const token = new URLSearchParams(window.location.search).get('token');
if (!token || token.length < 8) console.warn('Missing or truncated SSO recover token');

Type guard

function hasValidTokenShape(params) {
  const t = params.get('token');
  return typeof t === 'string' && /^[A-Za-z0-9_-]+$/.test(t) && t.length >= 16;
}

Try / catch

try {
  await completeSsoRecoverSuccess(token);
} catch (e) {
  if (e.message.includes('does not exist or has been deleted')) {
    restartSsoRecoverFlow(); // token consumed/missing: get a fresh one
  }
}

Prevention

When it happens

Trigger: GET /sso/recover/success/azure?token=... where the token value does not match any sso_authentication_tokens row: token already consumed by a previous success call, manually deleted, mistyped, or from a different environment/database.

Common situations: User refreshes the success page after the token was already used (single-use token consumed), replaying an old recovery link, or pointing a staging URL at a database where the token was never created.

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.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/75783a5d21e951e4. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/SsoRecover/src/Controller/Azure/AzureRecoverSuccessController.php:56

    }

    /**
     * @return void
     * @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
     */
    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)