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

  1. Decode the JWT and set the Dgraph `Audience` config to exactly match the token's `aud` value
  2. Or request a token from the IDP with the audience configured in Dgraph (check the token request's audience/resource parameter)
  3. 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

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


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/0a0ef46839b13de2. Report an issue: GitHub.