{"record":{"id":"be28d003fd26d2a7","repo":"dgraph-io/dgraph","slug":"unable-to-parse-jwt-token","errorCode":null,"errorMessage":"unable to parse jwt token","messagePattern":"unable to parse jwt token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"x/jwt_helper.go","lineNumber":45,"sourceCode":"\treturn k\n}\n\nfunc ParseJWT(jwtStr string) (jwt.MapClaims, error) {\n\ttoken, err := jwt.Parse(jwtStr, func(token *jwt.Token) (interface{}, error) {\n\t\tif WorkerConfig.AclJwtAlg == nil {\n\t\t\treturn nil, errors.Errorf(\"ACL is disabled\")\n\t\t}\n\t\tif token.Method.Alg() != WorkerConfig.AclJwtAlg.Alg() {\n\t\t\treturn nil, errors.Errorf(\"unexpected signing method in token: %v\", token.Header[\"alg\"])\n\t\t}\n\t\treturn MaybeKeyToBytes(WorkerConfig.AclPublicKey), nil\n\t})\n\tif err != nil {\n\t\t// This is for backward compatibility in clients\n\t\tif errors.Is(err, jwt.ErrTokenExpired) {\n\t\t\terr = errors.Wrap(errTokenExpired, jwt.ErrTokenInvalidClaims.Error())\n\t\t}\n\t\treturn nil, errors.Wrapf(err, \"unable to parse jwt token\")\n\t}\n\n\tclaims, ok := token.Claims.(jwt.MapClaims)\n\tif !ok || !token.Valid {\n\t\treturn nil, errors.Errorf(\"claims in jwt token is not map claims\")\n\t}\n\treturn claims, nil\n}\n\nfunc ExtractUserName(jwtToken string) (string, error) {\n\tclaims, err := ParseJWT(jwtToken)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tuserId, ok := claims[\"userid\"].(string)\n\tif !ok {\n\t\treturn \"\", errors.Errorf(\"userid in claims is not a string:%v\", userId)\n\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/x/jwt_helper.go#L27-L63","documentation":"Any failure from jwt.Parse (bad signature, malformed token, missing key, expired, etc.) is wrapped with errors.Wrapf(err, \"unable to parse jwt token\") and returned. This wrapper is the outermost message; the underlying cause (available via errors.Unwrap/%v of err) explains the actual problem. Parse fails validation, so no claims are returned.","triggerScenarios":"jwt.Parse returns any error during key-function callback (ACL disabled, wrong alg), signature verification failure, malformed token text, invalid claims, or expired token — via ParseJWT or its callers validateToken/ExtractUserName/ExtractNamespaceFromJwt.","commonSituations":"Wrong ACL public key configured so signatures never verify; truncated or whitespace-mangled token strings; tokens from a different cluster; the expired-token case above.","solutions":["Inspect the wrapped cause: print errors.Unwrap(err) or the full chain to see whether it is signature, alg, expiry, or key loading.","Verify WorkerConfig.AclPublicKey matches the private key that signed the token.","Confirm the raw JWT string is complete and unmodified (no truncation, quotes, or newlines) before ParseJWT.","Re-issue/refresh the token if the cause is expiry or wrong signing method."],"exampleFix":"// before: opaque handling\nif err != nil { return err }\n// after: surface the cause\nif err != nil {\n    return fmt.Errorf(\"jwt auth failed: %w\", err) // shows underlying reason\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"claims, err := x.ParseJWT(jwtToken)\nif err != nil {\n    // unwrap to classify the cause\n    switch {\n    case errors.Is(err, jwt.ErrTokenExpired):\n        // refresh token and retry\n    case strings.Contains(err.Error(), \"unexpected signing method\"):\n        // re-issue with correct alg\n    case strings.Contains(err.Error(), \"ACL is disabled\"):\n        // fix server config\n    default:\n        // log full error chain: fmt.Printf(\"%+v\", err)\n    }\n    return err\n}","preventionTips":["Log wrapped errors with %+v (pkg/errors stack trace) to see the root cause.","Validate the key/alg config before serving JWT-authenticated traffic.","Keep tokens intact in transit (no trimming/quoting) — transport them in a standard Authorization header.","Test auth flows after key rotations."],"tags":["jwt","parse","authentication","signature"],"backgroundTag":"jwt-parse-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}