{"record":{"id":"5cc1bd03cc29c0c1","repo":"ory/hydra","slug":"jwt-from-authorization-http-header-is-expecting-st","errorCode":null,"errorMessage":"jwt from authorization HTTP header is expecting string value for \"kid\" in tokenWithoutKid header but got: %T","messagePattern":"jwt from authorization HTTP header is expecting string value for \"kid\" in tokenWithoutKid header but got: %T","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/jwtmiddleware/middleware.go","lineNumber":106,"sourceCode":"\t\tErrorWriter:   herodot.NewJSONWriter(nil),\n\t}\n\n\tfor _, o := range opts {\n\t\to(c)\n\t}\n\tjc := jwksx.NewFetcher(wellKnownURL)\n\treturn &Middleware{\n\t\to:   c,\n\t\twku: wellKnownURL,\n\t\tjm: jwtmiddleware.New(\n\t\t\tfunc(ctx context.Context, rawToken string) (any, error) {\n\t\t\t\treturn jwt.NewParser(\n\t\t\t\t\tjwt.WithValidMethods([]string{c.SigningMethod.Alg()}),\n\t\t\t\t).Parse(rawToken, func(token *jwt.Token) (interface{}, error) {\n\t\t\t\t\tif raw, ok := token.Header[\"kid\"]; !ok {\n\t\t\t\t\t\treturn nil, errors.New(`jwt from authorization HTTP header is missing value for \"kid\" in token header`)\n\t\t\t\t\t} else if kid, ok := raw.(string); !ok {\n\t\t\t\t\t\treturn nil, fmt.Errorf(`jwt from authorization HTTP header is expecting string value for \"kid\" in tokenWithoutKid header but got: %T`, raw)\n\t\t\t\t\t} else if k, err := jc.GetKey(kid); err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn k.Key, nil\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t},\n\t\t\tjwtmiddleware.WithCredentialsOptional(false),\n\t\t\tjwtmiddleware.WithTokenExtractor(func(r *http.Request) (string, error) {\n\t\t\t\t// wrapping the extractor to get a herodot.ErrorContainer\n\t\t\t\ttoken, err := jwtmiddleware.AuthHeaderTokenExtractor(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn \"\", herodot.ErrUnauthorized().WithReason(err.Error())\n\t\t\t\t}\n\t\t\t\treturn token, nil\n\t\t\t}),\n\t\t\tjwtmiddleware.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {\n\t\t\t\tswitch {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/jwtmiddleware/middleware.go#L88-L124","documentation":"In the same key-resolution callback, the kid header value must be a JSON string. If token.Header[\"kid\"] exists but is not a string (e.g. a number or object produced by a broken issuer), this typed error reports the Go type that was found.","triggerScenarios":"A token whose kid header is a JSON number/bool/object — usually from a non-conformant token library or manual JWT construction (base64url-encoded header with \"kid\":123 instead of \"kid\":\"123\").","commonSituations":"Custom JWT minting code using numeric key ids; misconfigured issuer templates; debugging hand-crafted tokens in curl scripts.","solutions":["Fix the issuer to emit kid as a JSON string","Locally decode the token header (base64url of the first dot-segment) to confirm the kid type before debugging server-side","Re-encode/reissue the offending token; reject such tokens early in the issuer pipeline"],"exampleFix":"// before (hand-crafted header)\n{\"alg\":\"ES256\",\"kid\":42}\n// after\n{\"alg\":\"ES256\",\"kid\":\"42\"}","handlingStrategy":"type-guard","validationCode":"func kidIsString(rawJWT string) error {\n    parts := strings.Split(rawJWT, \".\")\n    if len(parts) != 3 { return errors.New(\"malformed token\") }\n    hdr, err := base64.RawURLEncoding.DecodeString(parts[0])\n    if err != nil { return err }\n    var h map[string]any\n    if err := json.Unmarshal(hdr, &h); err != nil { return err }\n    if v, ok := h[\"kid\"]; ok {\n        if _, isStr := v.(string); !isStr {\n            return fmt.Errorf(\"kid must be a JSON string, got %T\", v)\n        }\n    }\n    return nil\n}","typeGuard":"func kidAsString(header map[string]any) (string, bool) {\n    raw, present := header[\"kid\"]\n    if !present { return \"\", false }\n    kid, isStr := raw.(string)\n    return kid, isStr\n}","tryCatchPattern":"err := next(w, r.WithContext(ctx))\nif err != nil && strings.Contains(err.Error(), \"expecting string value for \\\"kid\\\"\") {\n    http.Error(w, \"token kid header must be a string\", http.StatusUnauthorized)\n}","preventionTips":["Fix non-conformant issuers that emit numeric kid values — RFC 7515 requires a string","Decode and inspect token headers in integration tests before deploying clients","Avoid hand-crafting JWT headers in scripts; use a maintained JWT library","Add issuer-side schema validation of the JOSE header"],"tags":["jwt","jwks","kid","auth","go"],"backgroundTag":"jwt-missing-kid","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"}