{"record":{"id":"b6ecf5f9c2883350","repo":"passbolt/passbolt_api","slug":"no-claims","errorCode":null,"errorMessage":"No claims","messagePattern":"No claims","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/OpenId/BaseIdToken.php","lineNumber":110,"sourceCode":"\n            throw $exception;\n        }\n\n        $this->idTokenClaims = $tokenClaims;\n    }\n\n    /**\n     * Validate the access token claims from an access token you received in your application.\n     * Note: nbf and exp claims are validated in JWT::decode\n     *\n     * @param array $tokenClaims The token claims from an access token you received in the authorization header.\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if any of the claim is invalid\n     * @return void\n     */\n    public function assertTokenClaims(array $tokenClaims): void\n    {\n        if (empty($tokenClaims)) {\n            throw new BadRequestException('No claims');\n        }\n\n        $this->assertAudClaim($tokenClaims);\n        $this->assertIssClaim($tokenClaims);\n        $this->assertEmailClaim($tokenClaims);\n    }\n\n    /**\n     * Validation email claim against application email validation rule\n     *\n     * @param array $tokenClaims claims\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the claim does not validate\n     */\n    public function assertEmailClaim(array $tokenClaims): void\n    {\n        $emailClaim = Configure::read('passbolt.plugins.sso.security.oauth2.emailClaimAlias') ?? 'email';\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/OpenId/BaseIdToken.php#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"Rare in practice; usually seen in unit tests calling assertTokenClaims([]) or when a hand-crafted/damaged JWT decoded to an empty payload.","solutions":["Re-obtain a fresh id_token from the provider — the current one has no usable payload.","Verify the token was not altered/stripped in transit (proxies or client code rewriting the token).","If calling assertTokenClaims directly (tests/tools), pass the full decoded claims array, not an empty one."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"$claims = (array)JWT::decode($idToken, $keys);\nif (empty($claims)) {\n    throw new RuntimeException('Decoded token has no claims; obtain a fresh id_token');\n}","typeGuard":"function hasClaims(array $tokenClaims): bool {\n    return !empty($tokenClaims);\n}","tryCatchPattern":"try {\n    $token->assertTokenClaims($claims);\n} catch (BadRequestException $e) {\n    if ($e->getMessage() === 'No claims') { /* token unusable: re-run OAuth flow */ }\n}","preventionTips":["Only feed assertTokenClaims with the full decoded JWT payload","Treat empty-claim tokens as corrupt: request a new id_token rather than retrying validation","Avoid manual token manipulation in tests that strips the payload"],"tags":["jwt","openid","claims","sso"],"backgroundTag":"empty-required-field","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}