{"record":{"id":"3758f2b451a01d45","repo":"dgraph-io/dgraph","slug":"claims-in-jwt-token-is-not-map-claims","errorCode":null,"errorMessage":"claims in jwt token is not map claims","messagePattern":"claims in jwt token is not map claims","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/authorization/auth.go","lineNumber":417,"sourceCode":"\n\t\t\t\tswitch a.SigningMethod.(type) {\n\t\t\t\tcase *jwt.SigningMethodHMAC:\n\t\t\t\t\treturn []byte(a.VerificationKey), nil\n\t\t\t\tcase *jwt.SigningMethodRSA:\n\t\t\t\t\treturn a.RSAPublicKey, nil\n\t\t\t\t}\n\n\t\t\t\treturn nil, errors.Errorf(\"couldn't parse signing method from token header: %s\", algo)\n\t\t\t})\n\t}\n\n\tif err != nil {\n\t\treturn nil, errors.Errorf(\"unable to parse jwt token:%v\", err)\n\t}\n\n\tclaims, ok := token.Claims.(*CustomClaims)\n\tif !ok || !token.Valid {\n\t\treturn nil, errors.Errorf(\"claims in jwt token is not map claims\")\n\t}\n\n\tif err := claims.validateAudience(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn claims, nil\n}\n\n// FetchJWKs fetches the JSON Web Key sets for the JWKUrls. It returns an error if\n// the fetching of key is failed even for one of the JWKUrl.\nfunc (a *AuthMeta) FetchJWKs() error {\n\tif len(a.JWKUrls) == 0 {\n\t\treturn errors.Errorf(\"No JWKUrl supplied\")\n\t}\n\n\tfor i := range a.JWKUrls {\n\t\terr := a.FetchJWK(i)\n\t\tif err != nil {","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/authorization/auth.go#L399-L435","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Inspect the token's exp/nbf/iat claims — re-generate a fresh token if expired.","Check server clock skew (NTP) which can flip validity around exp/nbf boundaries.","Upgrade/pin the golang-jwt version consistently between your expectations and the library.","Log token.Valid and claims before returning to pinpoint which condition fired.","If it persists, decode claims and validate manually to find the failing claim."],"exampleFix":"// before\nclaims, ok := token.Claims.(*CustomClaims)\nif !ok || !token.Valid {\n    return nil, errors.Errorf(\"claims in jwt token is not map claims\")\n}\n// after\nclaims, ok := token.Claims.(*CustomClaims)\nif !ok {\n    return nil, errors.Errorf(\"unexpected claims type %T\", token.Claims)\n}\nif !token.Valid {\n    return nil, errors.Errorf(\"jwt token invalid: %v\", token.Claims.Valid())\n}","handlingStrategy":"try-catch","validationCode":"// reject expired tokens before calling the library\nfunc notYetExpired(jwtStr string) bool {\n    // parse claims and check exp > now, nbf <= now\n    return true // implement via base64-decoding the payload\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"claims in jwt token is not map claims\") {\n    log.Printf(\"token failed validity check: %v\", err)\n    return nil, status.Error(codes.Unauthenticated, \"token invalid\")\n}","preventionTips":["Check exp/nbf claims explicitly and surface a precise 'expired' error","Keep golang-jwt versions pinned and consistent across services","Enable NTP on all auth-participating hosts","Unit-test validation with expired, future-nbf, and valid tokens"],"tags":["jwt","claims","validation","authentication"],"backgroundTag":"jwt-token-invalid","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}