passbolt/passbolt_api · error · BadRequestException

The aud (client id) parameter is invalid.

Error message

The aud (client id) parameter is invalid.

What it means

assertAudClaim verifies the `aud` claim contains this provider's configured client id (using strict in_array). If aud is missing, not a string/array, or does not include the expected client id, it throws BadRequestException('The aud (client id) parameter is invalid.'). This prevents tokens minted for another application from being accepted.

Solutions

  1. Decode the token (jwt.io or debugEnabled) and compare its `aud` value with the client id configured in passbolt's SSO provider settings.
  2. Update passbolt's SSO client ID setting to match the application the token was actually issued for.
  3. Ensure the client code exchanges the code and passes the id_token from the same client id that initiated login.
  4. Verify you are not confusing environments (staging client id used against production provider or vice versa).

Example fix

// before
'sso' => ['google' => ['clientId' => 'old-app-id.apps.googleusercontent.com']] // token aud is new-app-id
// after
'sso' => ['google' => ['clientId' => 'new-app-id.apps.googleusercontent.com']] // matches token aud
Defensive patterns

Strategy: validation

Validate before calling

$auds = (array)($claims['aud'] ?? []);
if (!in_array($expectedClientId, $auds, true)) {
    throw new RuntimeException('id_token aud does not include configured client id');
}

Type guard

function audienceIncludes(array $claims, string $clientId): bool {
    $aud = $claims['aud'] ?? null;
    $auds = is_array($aud) ? $aud : (is_string($aud) ? [$aud] : []);
    return in_array($clientId, $auds, true);
}

Try / catch

try {
    $token->assertTokenClaims($claims);
} catch (BadRequestException $e) {
    if (str_contains($e->getMessage(), 'aud (client id)')) { /* compare token aud vs configured clientId */ }
}

Prevention

When it happens

Trigger: assertTokenClaims runs assertAudClaim and the id_token's `aud` claim (string or array) does not contain $this->provider->getClientId() — typically the token was issued for a different client/application.

Common situations: Rotating or creating new OAuth client credentials without updating passbolt's SSO settings; mixing staging and production client ids across environments; passing an access token (whose aud differs) where an id_token is expected; multi-audience tokens with strict comparison edge cases.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — 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/830bf64c54b95324. Report an issue: GitHub.

Appendix: source

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

     * @throws \Cake\Http\Exception\BadRequestException if the claim does not validate
     */
    public function assertAudClaim(array $tokenClaims): void
    {
        if (isset($tokenClaims['aud'])) {
            if (is_string($tokenClaims['aud'])) {
                $auds[] = $tokenClaims['aud'];
            } else {
                $auds = $tokenClaims['aud'];
            }

            if (is_array($auds)) {
                if (in_array($this->provider->getClientId(), $auds, true)) {
                    return;
                }
            }
        }

        throw new BadRequestException('The aud (client id) parameter is invalid.');
    }

    /**
     * @return string id_token
     */
    public function getIdToken(): string
    {
        return $this->idToken;
    }

    /**
     * @return array claims from JWT::decode(id_token)
     */
    public function getIdTokenClaims(): array
    {
        return $this->idTokenClaims;
    }

View on GitHub (pinned to 31c1bbc10f)