dgraph-io/dgraph · error

a valid JWT is required but was not provided

Error message

a valid JWT is required but was not provided

What it means

`ExtractCustomClaims` pulls the JWT out of the gRPC context metadata. When no JWT is present in metadata and the AuthMeta is configured with ClosedByDefault (the GraphQL API is closed to unauthenticated access), it returns this error instead of allowing anonymous access. If ClosedByDefault is false, a missing JWT is silently allowed.

Source

Thrown at graphql/authorization/auth.go:317

			}
		}
	}
	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 {
		return nil, fmt.Errorf("invalid jwt auth token")
	}
	return a.validateJWTCustomClaims(jwtToken[0])
}

func GetJwtToken(ctx context.Context) string {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return ""
	}
	jwtToken := md.Get(string(AuthJwtCtxKey))
	if len(jwtToken) != 1 {
		return ""
	}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Attach a valid JWT to every request via the header named in the Dgraph.Authorization config (e.g. `Authorization: Bearer <token>` or X-Auth-Token)
  2. Or set ClosedByDefault=false if the schema should permit anonymous queries
  3. Verify the client actually sends the header (check proxy/ingress isn't stripping it) and that the header key matches the configured Header field

Example fix

// before
curl -X POST https://host/graphql -d '{"query":"{ me { name } }"}'
// after
curl -X POST https://host/graphql -H 'Authorization: Bearer eyJhbGciOi...' -d '{"query":"{ me { name } }"}'
Defensive patterns

Strategy: try-catch

Validate before calling

if (closedByDefault && !getAuthHeader()) {
  throw new Error('This schema requires a JWT on every request');
}

Try / catch

const res = await client.query(q);
if (res.errors?.some(e => e.message.includes('a valid JWT is required'))) {
  await refreshSession(); // attach token, then retry
}

Prevention

When it happens

Trigger: Querying a GraphQL schema whose Dgraph.Authorization header sets ClosedByDefault=true without attaching any JWT to the request — no value under the AuthJwtCtxKey in metadata, or the client never sent the configured auth header.

Common situations: Testing the API with curl/GraphiQL without logging in; the auth header name in Dgraph.Authorization (Header field) not matching the header the client sends; a proxy stripping the Authorization header; enabling closed-by-default security and forgetting to update clients.

Related errors


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