{"record":{"id":"910a21744d53a027","repo":"go-kit/kit","slug":"jwt-is-malformed","errorCode":null,"errorMessage":"JWT is malformed","messagePattern":"JWT is malformed","errorType":"exception","errorClass":"ErrTokenMalformed","httpStatus":401,"severity":"error","filePath":"auth/jwt/middleware.go","lineNumber":39,"sourceCode":"\n\t// JWTClaimsContextKey holds the key used to store the JWT Claims in the\n\t// context.\n\tJWTClaimsContextKey contextKey = \"JWTClaims\"\n)\n\nvar (\n\t// ErrTokenContextMissing denotes a token was not passed into the parsing\n\t// middleware's context.\n\tErrTokenContextMissing = errors.New(\"token up for parsing was not passed through the context\")\n\n\t// ErrTokenInvalid denotes a token was not able to be validated.\n\tErrTokenInvalid = errors.New(\"JWT was invalid\")\n\n\t// ErrTokenExpired denotes a token's expire header (exp) has since passed.\n\tErrTokenExpired = errors.New(\"JWT is expired\")\n\n\t// ErrTokenMalformed denotes a token was not formatted as a JWT.\n\tErrTokenMalformed = errors.New(\"JWT is malformed\")\n\n\t// ErrTokenNotActive denotes a token's not before header (nbf) is in the\n\t// future.\n\tErrTokenNotActive = errors.New(\"token is not valid yet\")\n\n\t// ErrUnexpectedSigningMethod denotes a token was signed with an unexpected\n\t// signing method.\n\tErrUnexpectedSigningMethod = errors.New(\"unexpected signing method\")\n)\n\n// NewSigner creates a new JWT generating middleware, specifying key ID,\n// signing string, signing method and the claims you would like it to contain.\n// Tokens are signed with a Key ID header (kid) which is useful for determining\n// the key to use for parsing. Particularly useful for clients.\nfunc NewSigner(kid string, key []byte, method jwt.SigningMethod, claims jwt.Claims) endpoint.Middleware {\n\treturn func(next endpoint.Endpoint) endpoint.Endpoint {\n\t\treturn func(ctx context.Context, request interface{}) (response interface{}, err error) {\n\t\t\ttoken := jwt.NewWithClaims(method, claims)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/go-kit/kit/blob/78fbbceece7bbcf073bee814a7772f4397ea756c/auth/jwt/middleware.go#L21-L57","documentation":"Returned by jwt.NewParser when the underlying jwt.ValidationError has the ValidationErrorMalformed bit set: the string pulled from the context is not parseable as a JWT at all. A valid JWT is three dot-separated base64url segments; anything else fails immediately.","triggerScenarios":"Storing the entire Authorization header, including the \"Bearer \" prefix, in jwt.JWTContextKey instead of the bare token; an empty string when the header is missing; a token truncated by logging/truncation or mangled by URL encoding; garbage values from a misconfigured proxy or a hand-built test context.","commonSituations":"RequestFunc forgets strings.TrimPrefix(header, \"Bearer \"); clients sending a raw API key or session id where a JWT is expected; copy-paste of tokens with newlines/quotes from terminal; gateways rewriting or double-encoding the Authorization header.","solutions":["Strip the auth scheme before storing: strings.TrimPrefix(r.Header.Get(\"Authorization\"), \"Bearer \")","Reject/401 early when the header is empty or lacks the Bearer scheme so garbage never reaches the parser","Verify the token has the shape header.payload.signature (two dots, non-empty segments) before invoking the endpoint","Regenerate/copy the token cleanly if it was truncated or mangled"],"exampleFix":"// before: whole header, \"Bearer \" included, stored as the token\nreturn context.WithValue(ctx, jwt.JWTContextKey, r.Header.Get(\"Authorization\"))\n\n// after: store only the bare token\nv := strings.TrimSpace(r.Header.Get(\"Authorization\"))\nv = strings.TrimPrefix(v, \"Bearer \")\nif v == \"\" {\n\treturn ctx // parser will surface the missing/malformed error as 401\n}\nreturn context.WithValue(ctx, jwt.JWTContextKey, v)","handlingStrategy":"try-catch","validationCode":"func looksLikeJWT(s string) bool {\n\tparts := strings.Split(s, \".\")\n\treturn len(parts) == 3 && parts[0] != \"\" && parts[1] != \"\" && parts[2] != \"\"\n}\n// apply to the value before storing it in jwt.JWTContextKey","typeGuard":"null","tryCatchPattern":"if _, err := ep(ctx, req); err != nil {\n\tif errors.Is(err, jwt.ErrTokenMalformed) {\n\t\t// 400/401: the client is not sending a real JWT — fix the sender, no retry\n\t}\n}","preventionTips":["Strip the Bearer prefix exactly once, in one shared RequestFunc","Validate the 3-segment shape at the transport boundary and reject early with 400","Never pass tokens through logs/shell copy-paste; move them via secret managers or headers only"],"tags":["go","go-kit","jwt","authentication","http-headers","token-format"],"backgroundTag":null,"analyzedSha":"78fbbceece7bbcf073bee814a7772f4397ea756c","analyzedAt":"2026-08-15T22:31:35.570Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}