Cap refresh chain lifetime via RefreshChainAbsoluteTTL
Sessions had an absolute cap (created_at + SessionAbsoluteTTL) but the JWT path only had per-token TTL on the refresh row, letting a well-behaved client refresh indefinitely. Add chain_started_at to authkit_tokens, copy it forward on every rotation, and reject in RefreshJWT when now > chainStartedAt + RefreshChainAbsoluteTTL. Default 30d, mirroring SessionAbsoluteTTL. Schema, verifier, queries, model, and integration test updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d3c5367492
commit
ca5525d4bd
11 changed files with 129 additions and 53 deletions
19
authkit.go
19
authkit.go
|
|
@ -61,11 +61,17 @@ type Config struct {
|
|||
SessionCookieSameSite http.SameSite
|
||||
|
||||
// JWT (HS256)
|
||||
JWTSecret []byte
|
||||
JWTIssuer string
|
||||
JWTAudience string
|
||||
AccessTokenTTL time.Duration
|
||||
RefreshTokenTTL time.Duration
|
||||
JWTSecret []byte
|
||||
JWTIssuer string
|
||||
JWTAudience string
|
||||
AccessTokenTTL time.Duration
|
||||
RefreshTokenTTL time.Duration
|
||||
// RefreshChainAbsoluteTTL caps the maximum lifetime of a refresh chain.
|
||||
// A user can refresh as often as they want within RefreshTokenTTL of the
|
||||
// last rotation, but the chain itself dies once now > chainStartedAt +
|
||||
// RefreshChainAbsoluteTTL — at which point the user must re-authenticate.
|
||||
// Mirrors SessionAbsoluteTTL on the session path.
|
||||
RefreshChainAbsoluteTTL time.Duration
|
||||
|
||||
// Single-use tokens
|
||||
EmailVerifyTTL time.Duration
|
||||
|
|
@ -173,6 +179,9 @@ func applyDefaults(cfg Config) Config {
|
|||
if cfg.RefreshTokenTTL == 0 {
|
||||
cfg.RefreshTokenTTL = 30 * 24 * time.Hour
|
||||
}
|
||||
if cfg.RefreshChainAbsoluteTTL == 0 {
|
||||
cfg.RefreshChainAbsoluteTTL = 30 * 24 * time.Hour
|
||||
}
|
||||
if cfg.EmailVerifyTTL == 0 {
|
||||
cfg.EmailVerifyTTL = 48 * time.Hour
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue