BerriAI/litellm · critical · ValueError
audience must be provided unless disable_audience_validation
Error message
audience must be provided unless disable_audience_validation=True
What it means
ValueError raised in _build_decode_kwargs (litellm/proxy/auth/handle_jwt.py): JWT decoding options are being built with audience=None while disable_audience_validation is False. The guard makes disabling audience verification an explicit choice - a config that simply lacks an audience (e.g. a model validator was bypassed or a config was constructed programmatically) must not silently skip audience checks, since that would accept cross-tenant tokens from other applications sharing the IdP's signing keys.
Source
Thrown at litellm/proxy/auth/handle_jwt.py:917
for key in ["kty", "kid", "n", "e", "x", "y", "crv"]:
if key in public_key:
jwk[key] = public_key[key]
return jwk
def _get_decode_options(
self,
audience: str | list[str] | None,
issuer: str | None = None,
disable_audience_validation: bool = False,
) -> dict | None:
# Disabling audience verification must be an explicit choice — never
# an implicit consequence of ``audience`` being None. Otherwise a
# caller that accidentally constructs a config with ``audience=None``
# (bypassing the model validator) would silently lose audience
# validation. Require callers to opt in via
# ``disable_audience_validation=True``.
if audience is None and not disable_audience_validation:
raise ValueError("audience must be provided unless disable_audience_validation=True")
options: Final[dict] = {}
if audience is None:
options["verify_aud"] = False
if issuer is None:
options["verify_iss"] = False
return options or None
def _decode_jwt_with_public_key(
self,
token: str,
public_key: dict | str,
audience: str | list[str] | None,
issuer: str | None = None,
options: dict | None = None,
disable_audience_validation: bool = False,
) -> dict:
decode_options: Final = (
optionsView on GitHub (pinned to 77b7c6c40c)
Solutions
- Set the audience: JWT_AUDIENCE env var or audience in litellm_jwtauth config, matching the aud claim your IdP mints (client_id or API identifier)
- If your tokens genuinely carry no aud claim, opt out explicitly with disable_audience_validation: true in litellm_jwtauth - and understand the cross-tenant acceptance risk
- Verify the token payload at jwt.io to see the exact aud value to configure
Example fix
# config.yaml - before
litellm_settings:
litellm_jwtauth:
jwt_public_key_url: https://idp.example.com/certs
# config.yaml - after
litellm_settings:
litellm_jwtauth:
jwt_public_key_url: https://idp.example.com/certs
audience: https://api.example.com # or: disable_audience_validation: true Defensive patterns
Strategy: validation
Validate before calling
def validate_audience_config(audience, disable_audience_validation: bool) -> None:
if audience is None and not disable_audience_validation:
raise ValueError(
"JWT auth config invalid: set 'audience' (matching the token's aud claim) "
"or explicitly set disable_audience_validation=true"
) Prevention
- Always configure audience when the IdP mints an aud claim - decode a sample token to read it
- Treat disable_audience_validation as a documented security exception, never a default
- Add a config lint step that rejects JWT auth configs lacking both audience and the explicit opt-out
When it happens
Trigger: JWT auth is active with no audience configured (no JWT_AUDIENCE / audience in litellm_jwtauth) and disable_audience_validation not set to true - e.g. after upgrading to a version that enforces this, or constructing litellm_jwtauth programmatically with audience=None.
Common situations: Older configs that never set an audience and relied on signature+expiry checks only; a version change turning the implicit skip into a hard error; code building JWTAuthManager settings directly with audience=None.
Related errors
- Validation fails: {e}
- Missing JWT Public Key URL from environment.
- OIDC UserInfo endpoint not configured. Set 'oidc_userinfo_en
- Invalid JWT Submitted
- Either 'host' or 'url' must be specified for redis.
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/5bc6d907e27ae8af.
Report an issue: GitHub.