BookStackApp/BookStack · critical · OidcInvalidTokenException

Missing token audience value

Error message

Missing token audience value

What it means

OIDC requires every ID token to carry an aud (audience) claim listing the client(s) the token was issued for. If the payload's aud claim is absent or empty, validateCommonClaims throws OidcInvalidTokenException('Missing token audience value'). Without aud there is no way to confirm the token was issued for your client.

Source

Thrown at app/Access/Oidc/OidcJwtWithClaims.php:164

     * Validate common claims for OIDC JWT tokens.
     * As per https://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation
     * and https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
     *
     * @throws OidcInvalidTokenException
     */
    protected function validateCommonClaims(string $clientId): void
    {
        // 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery)
        // MUST exactly match the value of the iss (issuer) Claim.
        if (empty($this->payload['iss']) || $this->issuer !== $this->payload['iss']) {
            throw new OidcInvalidTokenException('Missing or non-matching token issuer value');
        }

        // 2. The Client MUST validate that the aud (audience) Claim contains its client_id value registered
        // at the Issuer identified by the iss (issuer) Claim as an audience. The ID Token MUST be rejected
        // if the ID Token does not list the Client as a valid audience.
        if (empty($this->payload['aud'])) {
            throw new OidcInvalidTokenException('Missing token audience value');
        }

        $aud = is_string($this->payload['aud']) ? [$this->payload['aud']] : $this->payload['aud'];
        if (!in_array($clientId, $aud, true)) {
            throw new OidcInvalidTokenException('Token audience value did not match the expected client_id');
        }
    }
}

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Verify you are validating an ID token, not an access token — only ID tokens are guaranteed an aud claim for OIDC flows
  2. Check the decoded payload (base64url-decode the second segment) to confirm aud is actually present; if missing, fix the token source, not the validator
  3. In your IdP client settings, ensure the audience/client-id mapping is set so aud is always emitted
  4. If an intermediary rewrites the payload (claims trimming, mapping), whitelist aud so it survives

Example fix

// before: validating an access token
$token = $result->getAccessToken();
$validator->validateCommonTokenDetails($token, $clientId);
// after: validate the ID token, which carries aud
$validator->validateCommonTokenDetails($result->getIdToken(), $clientId);
Defensive patterns

Strategy: validation

Validate before calling

$payload = json_decode(base64_decode(strtr(explode('.', $token)[1], '-_', '+/') . '=='), true);
if (empty($payload['aud'])) {
    throw new UnexpectedValueException('Token has no aud claim — is this an ID token?');
}

Try / catch

try {
    $jwt->validateCommonTokenDetails($token, $clientId);
} catch (OidcInvalidTokenException $e) {
    if ($e->getMessage() === 'Missing token audience value') {
        throw new UnauthorizedException('ID token lacks aud claim — ensure you are validating an ID token, not an access token');
    }
    throw $e;
}

Prevention

When it happens

Trigger: validateCommonClaims($clientId) checks empty($this->payload['aud']) immediately after the issuer check. Triggers when: the IdP is misconfigured not to emit aud; the token is an access token (rather than an ID token) that omits aud; claim-mapping/mangling in middleware strips or renames aud; the token payload was decoded into $this->payload incorrectly (e.g. wrong key order or partially decoded).

Common situations: Feeding an opaque access token or userinfo response into an ID-token validator; IdP client configured without the audience mapping; custom claim filtering (e.g. a proxy that trims claims) removing aud; using a token type whose aud is named differently by the provider.

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/2fa3a5e5bc6a3e30. Report an issue: GitHub.