dgraph-io/dgraph · error
JWT `aud` value doesn't match with the audience
Error message
JWT `aud` value doesn't match with the audience
What it means
`validateAudience` compares each string in the JWT's `aud` claim against the configured Audience list using constant-time comparison. If no value matches, it returns this error, meaning the token is valid but was not issued for this Dgraph deployment per the configured audience.
Source
Thrown at graphql/authorization/auth.go:303
return nil
}
// If there is an audience claim, but no value provided, fail
if c.authMeta.Audience == nil {
return fmt.Errorf("audience value was expected but not provided")
}
var match = false
for _, audStr := range c.Audience {
for _, expectedAudStr := range c.authMeta.Audience {
if subtle.ConstantTimeCompare([]byte(audStr), []byte(expectedAudStr)) == 1 {
match = true
break
}
}
}
if !match {
return fmt.Errorf("JWT `aud` value doesn't match with the audience")
}
return nil
}
func (a *AuthMeta) ExtractCustomClaims(ctx context.Context) (*CustomClaims, error) {
if a == nil {
return &CustomClaims{}, nil
}
// return CustomClaims containing jwt and authvariables.
md, _ := metadata.FromIncomingContext(ctx)
jwtToken := md.Get(string(AuthJwtCtxKey))
if len(jwtToken) == 0 {
if a.ClosedByDefault {
return &CustomClaims{}, fmt.Errorf("a valid JWT is required but was not provided")
}
return &CustomClaims{}, nil
}
if len(jwtToken) > 1 {View on GitHub (pinned to 759e242be6)
Solutions
- Decode the JWT and set the Dgraph `Audience` config to exactly match the token's `aud` value
- Or request a token from the IDP with the audience configured in Dgraph (check the token request's audience/resource parameter)
- Check for casing/whitespace/URL-trailing-slash differences between the two values
Example fix
// before "Audience":["https://api.example.com/"] // token aud: https://api.example.com // after "Audience":["https://api.example.com"]
Defensive patterns
Strategy: validation
Validate before calling
const payload = JSON.parse(atob(jwt.split('.')[1]));
const auds = Array.isArray(payload.aud) ? payload.aud : [payload.aud].filter(Boolean);
if (auds.length && !auds.some(a => config.Audience?.includes(a))) {
throw new Error('JWT aud does not match configured Audience');
} Prevention
- Compare aud strings byte-for-byte (casing, slashes, whitespace)
- Request tokens with the correct audience parameter from your IDP
- Re-verify audience config after changing environments (dev/staging/prod)
When it happens
Trigger: Presenting a JWT whose `aud` claim (any of its values, when aud is an array) does not equal any entry in the Dgraph.Authorization Audience list — e.g. token minted for audience "web-app" but Dgraph expects "dgraph".
Common situations: Pointing Dgraph at a new IDP/environment (dev token used against prod); the IDP changed its default audience; a copy-pasted config with a stale audience string; audience casing or trailing-slash differences.
Related errors
- audience value was expected but not provided
- expecting either JWKUrl or JWKUrls, both were given
- expecting either JWKUrl/JWKUrls or (VerificationKey, Algo),
- required field missing in Dgraph.Authorization:%s
- invalid Bearer-formatted header value for JWT (%s)
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/0a0ef46839b13de2.
Report an issue: GitHub.