{"record":{"id":"7a70a18eaed8f613","repo":"kataras/iris","slug":"err-7a70a1","errorCode":null,"errorMessage":"err","messagePattern":"err","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"middleware/jwt/verifier.go","lineNumber":112,"sourceCode":"\t\t}\n\t}\n\n\treturn &Verifier{\n\t\tAlg:        signatureAlg,\n\t\tKey:        signatureKey,\n\t\tExtractors: []TokenExtractor{FromHeader, FromQuery},\n\t\tErrorHandler: func(ctx *context.Context, err error) {\n\t\t\tctx.StopWithError(401, context.PrivateError(err))\n\t\t},\n\t\tValidators: validators,\n\t}\n}\n\n// WithDecryption enables AES-GCM payload-only encryption.\nfunc (v *Verifier) WithDecryption(key, additionalData []byte) *Verifier {\n\t_, decrypt, err := jwt.GCM(key, additionalData)\n\tif err != nil {\n\t\tpanic(err) // important error before serve, stop everything.\n\t}\n\n\tv.Decrypt = decrypt\n\treturn v\n}\n\n// WithDefaultBlocklist attaches an in-memory blocklist storage\n// to invalidate tokens through server-side.\n// To invalidate a token simply call the Context.Logout method.\nfunc (v *Verifier) WithDefaultBlocklist() *Verifier {\n\tv.Blocklist = jwt.NewBlocklist(30 * time.Minute)\n\treturn v\n}\n\nfunc (v *Verifier) invalidate(ctx *context.Context) {\n\tif verifiedToken := GetVerifiedToken(ctx); verifiedToken != nil {\n\t\tv.Blocklist.InvalidateToken(verifiedToken.Token, verifiedToken.StandardClaims)\n\t\tctx.Values().Remove(claimsContextKey)","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/middleware/jwt/verifier.go#L94-L130","documentation":"Verifier.WithDecryption enables AES-GCM payload-only decryption via jwt.GCM. It panics when jwt.GCM returns an error, which happens when the key length is not a valid AES size (16, 24, or 32 bytes). Like WithEncryption, this is fail-fast at construction time.","triggerScenarios":"Calling verifier.WithDecryption(key, additionalData) with a key that is empty, too short (e.g. raw passphrase bytes), or otherwise not 16/24/32 bytes. The key must also be the same one used for encryption.","commonSituations":"Mismatched env configuration between services (encryptor got the real 32-byte key, verifier got a truncated copy); key stored with quotes/newlines included; forgetting to base64-decode before passing.","solutions":["Validate key length (16/24/32 bytes) before calling WithDecryption and fail with a clear log message.","Decode the key from its stored encoding (base64/hex) rather than passing the encoded string bytes.","Ensure both sides derive the identical key material (same env var, same decode step)."],"exampleFix":"// before\nv.WithDecryption([]byte(cfg.Key), nil) // cfg.Key is base64 text, wrong length\n// after\nkey, err := base64.StdEncoding.DecodeString(cfg.Key)\nif err != nil || (len(key) != 16 && len(key) != 24 && len(key) != 32) {\n    log.Fatal(\"invalid jwt decryption key\")\n}\nv.WithDecryption(key, nil)","handlingStrategy":"validation","validationCode":"key, err := base64.StdEncoding.DecodeString(os.Getenv(\"JWT_DEC_KEY\"))\nif err != nil {\n    log.Fatalf(\"bad jwt key encoding: %v\", err)\n}\nif n := len(key); n != 16 && n != 24 && n != 32 {\n    log.Fatalf(\"jwt key must be 16/24/32 bytes, got %d\", n)\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"jwt decryption setup failed: %v\", r)\n    }\n}()\nv.WithDecryption(key, aad)","preventionTips":["Share one key-loading helper between encryptor and verifier so both use identical bytes.","Strip whitespace/quotes from env-provided keys before decoding.","Assert key equality (or length) at startup with a paired encrypt/decrypt self-test."],"tags":["go","panic","jwt","aes-gcm","invalid-key","startup"],"backgroundTag":"invalid-encryption-key","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}