{"record":{"id":"f67aaf11fa2d4bf1","repo":"ory/hydra","slug":"header-body-and-signature-must-all-be-set","errorCode":null,"errorMessage":"header, body and signature must all be set","messagePattern":"header, body and signature must all be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fosite/token/jwt/jwt.go","lineNumber":177,"sourceCode":"}\n\nfunc decodeToken(token string, verificationKey interface{}) (*Token, error) {\n\tkeyFunc := func(*Token) (interface{}, error) { return verificationKey, nil }\n\treturn ParseWithClaims(token, MapClaims{}, keyFunc)\n}\n\nfunc validateToken(tokenStr string, verificationKey interface{}) (string, error) {\n\t_, err := decodeToken(tokenStr, verificationKey)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn getTokenSignature(tokenStr)\n}\n\nfunc getTokenSignature(token string) (string, error) {\n\tsplit := strings.Split(token, \".\")\n\tif len(split) != 3 {\n\t\treturn \"\", errors.New(\"header, body and signature must all be set\")\n\t}\n\treturn split[2], nil\n}\n\nfunc hashSHA256(in []byte) ([]byte, error) {\n\thash := sha256.New()\n\t_, err := hash.Write(in)\n\tif err != nil {\n\t\treturn []byte{}, errorsx.WithStack(err)\n\t}\n\treturn hash.Sum([]byte{}), nil\n}\n\nfunc assign(a, b map[string]interface{}) map[string]interface{} {\n\tfor k, w := range b {\n\t\tif _, ok := a[k]; ok {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/fosite/token/jwt/jwt.go#L159-L195","documentation":"getTokenSignature splits a JWS compact-serialization token on '.' and requires exactly three parts: header, body, signature. Any token with a different number of dot-separated segments is malformed and fails with this error before the signature is extracted.","triggerScenarios":"Calling GetSignature, generateToken, or validateToken with a token string that does not have exactly three dot-separated segments — e.g. nil/empty token, an opaque token passed where a JWT is expected, or a manually truncated token.","commonSituations":"Passing an opaque access token to a JWT-signing/verification function; a token truncated by a header size limit or log-strip middleware; constructing a JWT without a signature part in custom code.","solutions":["Ensure only JWTs produced by the fosite jwt.Signer (three dot-separated parts) are passed to these functions","Check upstream code that a non-empty, non-opaque token is forwarded — opaque tokens belong to HMAC strategies, not JWT validation","Log/verify the token shape (strings.Count(token, \".\") == 2) before calling GetSignature"],"exampleFix":"// before\nsig, err := getTokenSignature(opaqueToken)\n// after\nif strings.Count(token, \".\") != 2 {\n    return errors.New(\"not a JWT\")\n}\nsig, err := getTokenSignature(token)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isJWT(token string) bool {\n    parts := strings.Split(token, \".\")\n    return len(parts) == 3 && parts[0] != \"\" && parts[1] != \"\"\n}","tryCatchPattern":"sig, err := getTokenSignature(token)\nif err != nil && err.Error() == \"header, body and signature must all be set\" {\n    // treat token as opaque or reject request\n}","preventionTips":["Verify token format before passing to JWT-specific code paths","Never truncate or wrap tokens in middleware/logs","Route opaque tokens to HMAC strategies, JWTs to jwt.Signer/verification"],"tags":["jwt","fosite","malformed-token","parsing"],"backgroundTag":"malformed-jwt","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}