{"record":{"id":"537509947efa8361","repo":"ory/hydra","slug":"invalid-jwk-key","errorCode":null,"errorMessage":"invalid JWK key","messagePattern":"invalid JWK key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/josex/utils.go","lineNumber":36,"sourceCode":"\nimport (\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/go-jose/go-jose/v3\"\n)\n\n// LoadJSONWebKey returns a *jose.JSONWebKey for a given JSON string.\nfunc LoadJSONWebKey(json []byte, pub bool) (*jose.JSONWebKey, error) {\n\tvar jwk jose.JSONWebKey\n\terr := jwk.UnmarshalJSON(json)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !jwk.Valid() {\n\t\treturn nil, errors.New(\"invalid JWK key\")\n\t}\n\tif jwk.IsPublic() != pub {\n\t\treturn nil, errors.New(\"priv/pub JWK key mismatch\")\n\t}\n\treturn &jwk, nil\n}\n\n// LoadPublicKey loads a public key from PEM/DER/JWK-encoded data.\nfunc LoadPublicKey(data []byte) (interface{}, error) {\n\tinput := data\n\n\tblock, _ := pem.Decode(data)\n\tif block != nil {\n\t\tinput = block.Bytes\n\t}\n\n\t// Try to load SubjectPublicKeyInfo\n\tpub, err0 := x509.ParsePKIXPublicKey(input)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/josex/utils.go#L18-L54","documentation":"josex.LoadJSONWebKey unmarshals a JSON Web Key from JSON bytes and then validates it with jose.JSONWebKey.Valid(). If the parsed key is structurally incomplete or cryptographically unusable (missing key material, unsupported/absent key type), it returns 'invalid JWK key'. This guards callers from receiving a JWK that would later fail at signing or verification time.","triggerScenarios":"Calling LoadJSONWebKey(json, pub) where json unmarshals into a JSONWebKey whose Valid() is false: e.g. JSON missing the required fields for its key type (no kty, no n/e for RSA, no x/y for EC, empty k for oct), malformed base64url key material, or a kty jose-go cannot parse.","commonSituations":"Hand-edited or truncated JWK files; JWKS fetched from a server whose entry was corrupted or stripped of key material; config/environment variables holding incomplete key JSON; generating JWK JSON with another tool using parameters go-jose does not accept; passing a symmetric 'oct' JWK where an asymmetric one is expected.","solutions":["Regenerate or re-export the key JSON so it is complete for its kty (RSA needs n and e; EC needs crv, x, y; oct needs k), e.g. via josex.GenerateJWK / go-jose MarshalJSON","Validate the JWK JSON with a linter or by calling jose.JSONWebKey.UnmarshalJSON yourself and inspecting the error for the missing field","Re-fetch the JWKS from the issuer if the key came from a remote endpoint — the copy may be truncated or stale","Confirm the variable/secret holding the key JSON was not truncated by env-var length limits or shell escaping"],"exampleFix":"// before (incomplete EC JWK)\njson := []byte(`{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"...\"}`) // missing y\nkey, err := josex.LoadJSONWebKey(json, true)\n// after (complete JWK)\njson := []byte(`{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"...\",\"y\":\"...\"}`)\nkey, err := josex.LoadJSONWebKey(json, true)","handlingStrategy":"validation","validationCode":"func validJWKJSON(json []byte) error {\n\tvar jwk jose.JSONWebKey\n\tif err := jwk.UnmarshalJSON(json); err != nil {\n\t\treturn fmt.Errorf(\"unmarshal JWK: %w\", err)\n\t}\n\tif !jwk.Valid() {\n\t\treturn errors.New(\"JWK is structurally invalid (missing key material for its kty)\")\n\t}\n\treturn nil\n}\n// call before: if err := validJWKJSON(keyJSON); err != nil { ... }","typeGuard":"func isValidJWK(raw []byte) bool {\n\tvar jwk jose.JSONWebKey\n\tif err := jwk.UnmarshalJSON(raw); err != nil {\n\t\treturn false\n\t}\n\treturn jwk.Valid()\n}","tryCatchPattern":"key, err := josex.LoadJSONWebKey(json, true)\nif err != nil {\n\tswitch {\n\tcase err.Error() == \"invalid JWK key\":\n\t\treturn fmt.Errorf(\"JWK JSON is incomplete or unsupported: %w\", err)\n\tcase err.Error() == \"priv/pub JWK key mismatch\":\n\t\treturn fmt.Errorf(\"expected a public key but got private (or vice versa): %w\", err)\n\tdefault:\n\t\treturn fmt.Errorf(\"loading JWK: %w\", err)\n\t}\n}","preventionTips":["Generate JWK JSON via josex.GenerateJWK or go-jose MarshalJSON instead of hand-writing it","Check that RSA JWKs contain n and e, EC JWKs contain crv/x/y, and oct JWKs contain a non-empty k","Beware env-var size limits and shell quoting when storing key JSON in configuration","When loading from a JWKS endpoint, re-fetch and log the raw entry when validation fails","Verify the pub flag matches whether the embedded key material is public or private"],"tags":["go","jose","jwk","key-parsing","validation"],"backgroundTag":"invalid-jwk","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"}