kataras/iris · critical

err

Error message

err

What it means

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.

Source

Thrown at middleware/jwt/verifier.go:112

		}
	}

	return &Verifier{
		Alg:        signatureAlg,
		Key:        signatureKey,
		Extractors: []TokenExtractor{FromHeader, FromQuery},
		ErrorHandler: func(ctx *context.Context, err error) {
			ctx.StopWithError(401, context.PrivateError(err))
		},
		Validators: validators,
	}
}

// WithDecryption enables AES-GCM payload-only encryption.
func (v *Verifier) WithDecryption(key, additionalData []byte) *Verifier {
	_, decrypt, err := jwt.GCM(key, additionalData)
	if err != nil {
		panic(err) // important error before serve, stop everything.
	}

	v.Decrypt = decrypt
	return v
}

// WithDefaultBlocklist attaches an in-memory blocklist storage
// to invalidate tokens through server-side.
// To invalidate a token simply call the Context.Logout method.
func (v *Verifier) WithDefaultBlocklist() *Verifier {
	v.Blocklist = jwt.NewBlocklist(30 * time.Minute)
	return v
}

func (v *Verifier) invalidate(ctx *context.Context) {
	if verifiedToken := GetVerifiedToken(ctx); verifiedToken != nil {
		v.Blocklist.InvalidateToken(verifiedToken.Token, verifiedToken.StandardClaims)
		ctx.Values().Remove(claimsContextKey)

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Validate key length (16/24/32 bytes) before calling WithDecryption and fail with a clear log message.
  2. Decode the key from its stored encoding (base64/hex) rather than passing the encoded string bytes.
  3. Ensure both sides derive the identical key material (same env var, same decode step).

Example fix

// before
v.WithDecryption([]byte(cfg.Key), nil) // cfg.Key is base64 text, wrong length
// after
key, err := base64.StdEncoding.DecodeString(cfg.Key)
if err != nil || (len(key) != 16 && len(key) != 24 && len(key) != 32) {
    log.Fatal("invalid jwt decryption key")
}
v.WithDecryption(key, nil)
Defensive patterns

Strategy: validation

Validate before calling

key, err := base64.StdEncoding.DecodeString(os.Getenv("JWT_DEC_KEY"))
if err != nil {
    log.Fatalf("bad jwt key encoding: %v", err)
}
if n := len(key); n != 16 && n != 24 && n != 32 {
    log.Fatalf("jwt key must be 16/24/32 bytes, got %d", n)
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Fatalf("jwt decryption setup failed: %v", r)
    }
}()
v.WithDecryption(key, aad)

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/7a70a18eaed8f613. Report an issue: GitHub.