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
|
|
@ -15,8 +15,8 @@ func (a *Auth) storeCreateToken(ctx context.Context, t *Token) error {
|
|||
}
|
||||
_, err := a.db.ExecContext(ctx, a.q.createToken,
|
||||
t.Hash, string(t.Kind), uuidArg(t.UserID), chainArg(t.ChainID),
|
||||
nullableTime(t.ConsumedAt), nullableInt(t.AttemptsRemaining),
|
||||
t.CreatedAt, t.ExpiresAt)
|
||||
nullableTime(t.ChainStartedAt), nullableTime(t.ConsumedAt),
|
||||
nullableInt(t.AttemptsRemaining), t.CreatedAt, t.ExpiresAt)
|
||||
if err != nil {
|
||||
return errx.Wrap(op, err)
|
||||
}
|
||||
|
|
@ -110,14 +110,15 @@ func (a *Auth) storeDeleteExpiredTokens(ctx context.Context, now time.Time) (int
|
|||
|
||||
func scanToken(row rowScanner) (*Token, error) {
|
||||
var (
|
||||
t Token
|
||||
kind string
|
||||
userIDStr string
|
||||
chainID sql.NullString
|
||||
consumedAt sql.NullTime
|
||||
attempts sql.NullInt32
|
||||
t Token
|
||||
kind string
|
||||
userIDStr string
|
||||
chainID sql.NullString
|
||||
chainStartedAt sql.NullTime
|
||||
consumedAt sql.NullTime
|
||||
attempts sql.NullInt32
|
||||
)
|
||||
if err := row.Scan(&t.Hash, &kind, &userIDStr, &chainID,
|
||||
if err := row.Scan(&t.Hash, &kind, &userIDStr, &chainID, &chainStartedAt,
|
||||
&consumedAt, &attempts, &t.CreatedAt, &t.ExpiresAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -128,6 +129,7 @@ func scanToken(row rowScanner) (*Token, error) {
|
|||
}
|
||||
t.UserID = uid
|
||||
t.ChainID = scanNullStringPtr(chainID)
|
||||
t.ChainStartedAt = scanNullTimePtr(chainStartedAt)
|
||||
t.ConsumedAt = scanNullTimePtr(consumedAt)
|
||||
t.AttemptsRemaining = scanNullIntPtr(attempts)
|
||||
return &t, nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue