dgraph-io/dgraph · error

claims in jwt token is not map claims

Error message

claims in jwt token is not map claims

What it means

After parsing succeeds, the library asserts the parsed claims are of its internal *CustomClaims type and that the token is valid. If the assertion fails or token.Valid is false, this (misleadingly named) error is returned. In practice the type assertion almost always succeeds, so hitting this usually means the token failed validity checks (expired claims, invalid signature flags) despite no earlier error.

Source

Thrown at graphql/authorization/auth.go:417

				switch a.SigningMethod.(type) {
				case *jwt.SigningMethodHMAC:
					return []byte(a.VerificationKey), nil
				case *jwt.SigningMethodRSA:
					return a.RSAPublicKey, nil
				}

				return nil, errors.Errorf("couldn't parse signing method from token header: %s", algo)
			})
	}

	if err != nil {
		return nil, errors.Errorf("unable to parse jwt token:%v", err)
	}

	claims, ok := token.Claims.(*CustomClaims)
	if !ok || !token.Valid {
		return nil, errors.Errorf("claims in jwt token is not map claims")
	}

	if err := claims.validateAudience(); err != nil {
		return nil, err
	}
	return claims, nil
}

// FetchJWKs fetches the JSON Web Key sets for the JWKUrls. It returns an error if
// the fetching of key is failed even for one of the JWKUrl.
func (a *AuthMeta) FetchJWKs() error {
	if len(a.JWKUrls) == 0 {
		return errors.Errorf("No JWKUrl supplied")
	}

	for i := range a.JWKUrls {
		err := a.FetchJWK(i)
		if err != nil {

View on GitHub (pinned to 759e242be6)

Solutions

  1. Inspect the token's exp/nbf/iat claims — re-generate a fresh token if expired.
  2. Check server clock skew (NTP) which can flip validity around exp/nbf boundaries.
  3. Upgrade/pin the golang-jwt version consistently between your expectations and the library.
  4. Log token.Valid and claims before returning to pinpoint which condition fired.
  5. If it persists, decode claims and validate manually to find the failing claim.

Example fix

// before
claims, ok := token.Claims.(*CustomClaims)
if !ok || !token.Valid {
    return nil, errors.Errorf("claims in jwt token is not map claims")
}
// after
claims, ok := token.Claims.(*CustomClaims)
if !ok {
    return nil, errors.Errorf("unexpected claims type %T", token.Claims)
}
if !token.Valid {
    return nil, errors.Errorf("jwt token invalid: %v", token.Claims.Valid())
}
Defensive patterns

Strategy: try-catch

Validate before calling

// reject expired tokens before calling the library
func notYetExpired(jwtStr string) bool {
    // parse claims and check exp > now, nbf <= now
    return true // implement via base64-decoding the payload
}

Try / catch

if err != nil && strings.Contains(err.Error(), "claims in jwt token is not map claims") {
    log.Printf("token failed validity check: %v", err)
    return nil, status.Error(codes.Unauthenticated, "token invalid")
}

Prevention

When it happens

Trigger: token, ok := token.Claims.(*CustomClaims); !ok || !token.Valid — raised in validateJWTCustomClaims after ParseWithClaims returned nil error but the token was rejected by claim validation, or claims type mismatch (only possible if the parse target changed).

Common situations: Token with nbf in the future or expired while err was nil in an older jwt lib version; token rejected by time-based claim validation; unexpected library version where ParseWithClaims behaves differently; custom middleware altering token/claims after parse.

Related errors


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