crewAIInc/crewAI · error · HTTPException

Invalid token audience

Error message

Invalid token audience

What it means

Raised by OIDCAuth.authenticate() when jwt.decode() throws InvalidAudienceError: the JWT's `aud` claim does not match the `audience` configured on the scheme. This is the server refusing a token minted for a different API/client. It maps to HTTP 401 and logs reason='invalid_audience'.

Source

Thrown at lib/crewai/src/crewai/a2a/auth/server_schemes.py:315

                scheme="oidc",
                claims=claims,
            )

        except jwt.ExpiredSignatureError:
            logger.debug(
                "OIDC authentication failed",
                extra={"reason": "token_expired", "scheme": "oidc"},
            )
            raise HTTPException(
                status_code=HTTP_401_UNAUTHORIZED,
                detail="Token has expired",
            ) from None
        except jwt.InvalidAudienceError:
            logger.debug(
                "OIDC authentication failed",
                extra={"reason": "invalid_audience", "scheme": "oidc"},
            )
            raise HTTPException(
                status_code=HTTP_401_UNAUTHORIZED,
                detail="Invalid token audience",
            ) from None
        except jwt.InvalidIssuerError:
            logger.debug(
                "OIDC authentication failed",
                extra={"reason": "invalid_issuer", "scheme": "oidc"},
            )
            raise HTTPException(
                status_code=HTTP_401_UNAUTHORIZED,
                detail="Invalid token issuer",
            ) from None
        except jwt.MissingRequiredClaimError as e:
            logger.debug(
                "OIDC authentication failed",
                extra={"reason": "missing_claim", "claim": e.claim, "scheme": "oidc"},
            )
            raise HTTPException(

View on GitHub (pinned to 754d7323be)

Solutions

  1. Check the token's aud claim (decode without verification: jwt.decode(tok, options={'verify_signature': False})['aud']) and align the scheme's `audience` with the value your IdP issues for this API.
  2. In Auth0, use the API Identifier (e.g. https://myapi) as both the requested audience and the scheme's audience, not the client_id.
  3. Ensure the client requests that audience during the token flow (audience parameter in the authorize/token request).
  4. If the token legitimately has multiple audiences, pass audience as a list accepted by PyJWT.

Example fix

# before
auth = OIDCAuth(jwks_url=jwks, audience="abc123clientid", ...)  # client_id used by mistake

# after
auth = OIDCAuth(jwks_url=jwks, audience="https://my-api.example.com", ...)  # API identifier as issued in `aud`
Defensive patterns

Strategy: validation

Validate before calling

import jwt

claims = jwt.decode(access_token, options={"verify_signature": False})
assert claims.get("aud") == configured_audience, (
    f"aud mismatch: token={claims.get('aud')!r} scheme={configured_audience!r}"
)

Prevention

When it happens

Trigger: Scheme configured with audience='crewai-a2a' but the token was issued with aud='some-other-api'; audience configured as the OAuth2 client_id instead of the API identifier (common Auth0 mix-up); token issued for multiple audiences where none matches.

Common situations: Auth0 setups where developers put the client_id in audience instead of the API identifier; copying the audience from a different environment's provider config; reusing a token obtained for another downstream service.

Understand the failure class

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/c2d7a9fb92b9de7a. Report an issue: GitHub.