passbolt/passbolt_api · error · BadRequestException

No claims

Error message

No claims

What it means

assertTokenClaims is the entry point for validating the decoded JWT claims. If the claims array decoded from the id_token is empty, it throws BadRequestException('No claims') before running the individual aud/iss/email assertions. An empty claim set means the token carried no payload data at all.

Solutions

  1. Re-obtain a fresh id_token from the provider — the current one has no usable payload.
  2. Verify the token was not altered/stripped in transit (proxies or client code rewriting the token).
  3. If calling assertTokenClaims directly (tests/tools), pass the full decoded claims array, not an empty one.
Defensive patterns

Strategy: validation

Validate before calling

$claims = (array)JWT::decode($idToken, $keys);
if (empty($claims)) {
    throw new RuntimeException('Decoded token has no claims; obtain a fresh id_token');
}

Type guard

function hasClaims(array $tokenClaims): bool {
    return !empty($tokenClaims);
}

Try / catch

try {
    $token->assertTokenClaims($claims);
} catch (BadRequestException $e) {
    if ($e->getMessage() === 'No claims') { /* token unusable: re-run OAuth flow */ }
}

Prevention

When it happens

Trigger: assertTokenClaims called (directly or via __construct during token instantiation) with an empty array — i.e. JWT::decode succeeded but produced no claims, or a caller passed an empty array manually.

Common situations: Rare in practice; usually seen in unit tests calling assertTokenClaims([]) or when a hand-crafted/damaged JWT decoded to an empty payload.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/OpenId/BaseIdToken.php:110

            throw $exception;
        }

        $this->idTokenClaims = $tokenClaims;
    }

    /**
     * Validate the access token claims from an access token you received in your application.
     * Note: nbf and exp claims are validated in JWT::decode
     *
     * @param array $tokenClaims The token claims from an access token you received in the authorization header.
     * @throws \Cake\Http\Exception\BadRequestException if any of the claim is invalid
     * @return void
     */
    public function assertTokenClaims(array $tokenClaims): void
    {
        if (empty($tokenClaims)) {
            throw new BadRequestException('No claims');
        }

        $this->assertAudClaim($tokenClaims);
        $this->assertIssClaim($tokenClaims);
        $this->assertEmailClaim($tokenClaims);
    }

    /**
     * Validation email claim against application email validation rule
     *
     * @param array $tokenClaims claims
     * @return void
     * @throws \Cake\Http\Exception\BadRequestException if the claim does not validate
     */
    public function assertEmailClaim(array $tokenClaims): void
    {
        $emailClaim = Configure::read('passbolt.plugins.sso.security.oauth2.emailClaimAlias') ?? 'email';

View on GitHub (pinned to 31c1bbc10f)