fix(cache,jwt): bound grace, resize, memory cap and time claims

Grace extensions overwrote ExpiresAt, so a polled stale entry never hit
MaxGracePeriod. The bound now uses the first expiry.

SetMaxSize with a non-positive size spun the eviction loop forever. It
now clamps to 1.

One value larger than MaxMemoryBytes flushed every other entry and left
the cache over its cap. The cache now drops that value.

int64(float64) wrapped a far-future nbf or iat into the past, so the
token passed. Non-finite and out-of-range claims now fail.
This commit is contained in:
2026-11-03 00:37:12 +00:00
parent a1b7059da1
commit 621f7993a8
3 changed files with 134 additions and 2 deletions
+8
View File
@@ -7,6 +7,7 @@ import (
"crypto/rsa"
"encoding/base64"
"fmt"
"math"
"math/big"
"strings"
"time"
@@ -231,6 +232,9 @@ func verifyIssuer(tokenIssuer, expectedIssuer string) error {
return nil
}
// maxClaimUnix is 9999-12-31T23:59:59Z, the largest time claim accepted.
const maxClaimUnix = 253402300799
// verifyTimeConstraint validates time-based JWT claims with clock skew tolerance.
// It handles both future constraints (exp) and past constraints (iat, nbf).
// Parameters:
@@ -241,6 +245,10 @@ func verifyIssuer(tokenIssuer, expectedIssuer string) error {
// Returns:
// - An error describing the failure (e.g., "token has expired", "token used before issued")
func verifyTimeConstraint(unixTime float64, claimName string, future bool) error {
// int64(float64) wraps out of range, which put a far-future nbf/iat in the past.
if math.IsNaN(unixTime) || math.IsInf(unixTime, 0) || math.Abs(unixTime) > maxClaimUnix {
return fmt.Errorf("token %s claim out of range", claimName)
}
claimTime := time.Unix(int64(unixTime), 0)
now := time.Now()