Authentication2026-03-27

'"audiences in jwt are not allowed" — What It Means and How to Fix It'

Learn why you're seeing "audiences in jwt are not allowed" and how to fix JWT audience validation errors in your application.

jwtauthenticationerrordebuggingoauth

"audiences in jwt are not allowed" — What It Means and How to Fix It

If you've hit the error "audiences in jwt are not allowed" or a close variant like "jwt audience invalid" or "aud claim mismatch", you're dealing with one of the most common JWT validation failures in production systems. It looks cryptic, but the fix is usually straightforward once you understand what the aud claim actually does.

What Is the aud Claim in a JWT?

A JWT (JSON Web Token) is made up of three parts: a header, a payload, and a signature. The payload contains claims — key-value pairs that assert information about the token subject or the token itself.

The aud (audience) claim is a registered claim defined in RFC 7519. It identifies the intended recipients of the token. When a service receives a JWT, it should reject the token if it does not identify itself as an intended audience.

Here is what a decoded JWT payload with an aud claim looks like:

{
  "sub": "1234567890",
  "name": "Jane Smith",
  "iat": 1711497600,
  "exp": 1711501200,
  "iss": "https://auth.example.com",
  "aud": "https://api.example.com"
}

The aud value can be a single string or an array of strings:

{
  "aud": ["https://api.example.com", "https://admin.example.com"]
}

The receiving service must check that its own identifier appears in that list. If the identifiers don't match, the token is rejected.

Why Does "audiences in jwt are not allowed" Happen?

This specific error message typically comes from libraries that, by default, refuse to process tokens containing an aud claim unless you have explicitly configured what audience to expect.

The logic is defensive: if your code doesn't know what audience to validate against, the library would rather fail closed than silently accept a token intended for a different service. A token issued for your payment API should not be accepted by your user profile API.

The three most common causes:

  1. You have not configured audience validation. The token has an aud claim, but your JWT library has no audience option set.
  2. The audience in the token doesn't match what your service expects. The token says aud: "https://api.example.com" but your service checks for aud: "api.example.com" — a common trailing-slash or scheme mismatch.
  3. You are using a token issued for a different environment. A staging token reaching a production validator, for instance.

Inspecting the aud Claim

Before writing any code, paste your token into the JWT Decoder to see exactly what aud value is present. No server calls, no logging — the decoder parses the payload client-side in your browser.

If you want to trace the full OIDC flow and see what audience your identity provider is issuing, the OIDC Debugger lets you walk through the discovery document and token exchange interactively.

Fixing the Error by Framework

Node.js with jsonwebtoken

// This will throw if the token has an aud claim
jwt.verify(token, secret);

// Correct: tell the library what audience to expect
jwt.verify(token, secret, {
  audience: 'https://api.example.com',
  issuer: 'https://auth.example.com',
});

Python with PyJWT

import jwt

payload = jwt.decode(
    token,
    secret,
    algorithms=["HS256"],
    audience="https://api.example.com",
    issuer="https://auth.example.com",
)

For temporary debugging only — never in production:

payload = jwt.decode(
    token,
    secret,
    algorithms=["HS256"],
    options={"verify_aud": False},
)

.NET / ASP.NET Core

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = "https://auth.example.com/";
        options.Audience = "https://api.example.com";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = true,
            ValidAudience = "https://api.example.com",
        };
    });

If your ValidAudience is already set but you still see the error, double-check trailing slashes. https://api.example.com and https://api.example.com/ are treated as different strings.

Auth0 / Okta / Azure AD

These identity providers set the aud claim to the API identifier (Auth0) or Application ID URI (Azure AD) you configure when registering your API. The value in your validator must exactly match what is configured in your IdP dashboard.

For Auth0, the audience is typically the API identifier you created in the dashboard — something like https://api.example.com. For Azure AD it is the Application ID URI, which often looks like api://your-client-id.

Configuring Audience Validation Correctly

A few rules to follow:

  • Always validate audience in production. Skipping aud validation means a token intended for Service A will be accepted by Service B if it passes signature verification.
  • Use exact string matching. Most libraries do a case-sensitive comparison. Trailing slashes, schemes, and ports all matter.
  • Match what your IdP actually issues. Use the JWT Decoder to read the raw aud value from a real token, then configure your service to expect exactly that string.
  • Multiple audiences are supported. If your service needs to accept tokens for more than one audience, most libraries accept an array.

Quick Diagnostic Checklist

  1. Decode the token at jwt-decoder — what is the exact aud value?
  2. What does your library's audience config say? Are they byte-for-byte identical?
  3. Is the token expired (exp claim)? A different error may be masking the real one.
  4. Is the iss (issuer) claim correct? Some libraries validate issuer and audience together.
  5. Are you in the right environment? Staging tokens usually have different audience values than production.

The error is the library doing its job. Once you align the aud claim value in the token with the expected audience in your validator, the error disappears.