passbolt/passbolt_api · error · BadRequestException

The authentication token does not exist.

Error message

The authentication token does not exist.

What it means

In SsoKeysGetService::get(), the SSO authentication token is fetched via SsoAuthenticationTokenGetService::getOrFail(); if the token record does not exist, RecordNotFoundException('The authentication token does not exist.') is re-thrown as BadRequestException. The token is the secret handed to the browser during the SSO key exchange and must exist (and later pass assertAndConsume) before the SSO key is returned.

Solutions

  1. Restart the SSO login/key-exchange flow from the beginning so a fresh token is generated
  2. Do not reuse a token once the SSO key was fetched — each token is single-use
  3. Check the sso_authentication_tokens table to confirm the token id exists
  4. Ensure the client is not double-submitting the request (e.g. retries after a timeout)

Example fix

// before: reuse consumed token on page refresh
await getSsoKey(oldTokenId);
// after: restart flow to obtain a new token
const {token} = await startSsoKeyExchange();
await getSsoKey(token);
Defensive patterns

Strategy: try-catch

Validate before calling

// check token exists and is unconsumed before calling
$token = $SsoAuthTokens->find()->where(['id' => $tokenId, 'active' => true])->first();
if (!$token) {
    restartSsoFlow();
}

Try / catch

try {
    $key = $ssoKeysGetService->get($uac, $token, $keyId);
} catch (BadRequestException $e) {
    if (str_contains($e->getMessage(), 'authentication token does not exist')) {
        return $this->restartSsoFlow(); // token used/expired
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling the SSO keys get endpoint with a token id that was never created, was already consumed by a prior call (assertAndConsume consumes it), or expired/was deleted.

Common situations: Replaying an SSO key-exchange token after it was already used in a previous request; browser refresh re-submitting a used token; clocks/expiry cleanup removing the token; copy-pasting a token from another session.

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/2aeeba863a044a0a. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Service/SsoKeys/SsoKeysGetService.php:50

     *
     * @param \App\Utility\ExtendedUserAccessControl $uac extended user access control
     * @param string $token SsoAuthenticationToken.token
     * @param string $keyId uuid
     * @return \Passbolt\Sso\Model\Entity\SsoKey
     */
    public function get(ExtendedUserAccessControl $uac, string $token, string $keyId): SsoKey
    {
        try {
            $ssoSettingEntity = (new SsoSettingsGetService())->getActiveOrFail();
            // Token must be provided and matching the settings, user id, ip, user agent, etc.
            $ssoAuthTokenGetService = new SsoAuthenticationTokenGetService();
            $ssoAuthToken = $ssoAuthTokenGetService->getOrFail(
                $token,
                SsoState::TYPE_SSO_GET_KEY
            );
            $ssoAuthTokenGetService->assertAndConsume($ssoAuthToken, $uac, $ssoSettingEntity->id);
        } catch (RecordNotFoundException $exception) {
            throw new BadRequestException($exception->getMessage(), 400, $exception);
        }

        try {
            $SsoKeys = TableRegistry::getTableLocator()->get('Passbolt/Sso.SsoKeys');
            /** @var \Passbolt\Sso\Model\Entity\SsoKey $key entity */
            $key = $SsoKeys->find()->where(['id' => $keyId, 'user_id' => $uac->getId()])->firstOrFail();
        } catch (RecordNotFoundException $exception) {
            throw new RecordNotFoundException(__('The SSO key does not exist.'), 404, $exception);
        }

        return $key;
    }
}

View on GitHub (pinned to 31c1bbc10f)