Skip to content

Access tokens effectively live ~16 min, not the documented 15 (60s leeway) #16

Closed

Description

@jjbaumert

Summary: crates/auth/src/jwt.rs documents and constants a 15-minute access-token TTL (ACCESS_TOKEN_TTL_SECS: u64 = 15 * 60, doc comment "Access token lifetime: 15 minutes." at line 30). validate_token builds Validation::new(Algorithm::HS256) (line 79) without setting leeway, so it inherits jsonwebtoken's default 60-second leeway — a token presented up to 60 seconds after its nominal expiry is still accepted. The effective token lifetime is therefore ~16 minutes, not the 15 minutes documented and presumably relied on elsewhere (session-length assumptions, revocation-window reasoning).

Severity: S4 — latent/internal. A 60-second extension of a 15-minute token isn't a meaningful security exposure on its own, but it's an undocumented, implicit discrepancy between the stated contract and the actual behavior, now pinned by a characterization test rather than deliberately chosen.

Environment:

Repro steps:

  1. Mint a JWT with exp set to 5 seconds in the past.
  2. Call validate_token on it.
  3. Observe it validates successfully (within the 60s leeway).
  4. Mint a JWT with exp set to 120 seconds in the past; observe it correctly fails with TokenExpired.

Expected: Either the leeway is a deliberate, documented choice (and the "15 minutes" doc comment should say "15 minutes + up to 60s leeway"), or the leeway should be set to 0 to match the documented contract exactly.

Observed: jsonwebtoken's default 60-second Validation leeway applies silently; nothing in crates/auth/src/jwt.rs sets or documents it near the ACCESS_TOKEN_TTL_SECS constant.

Evidence:

  • Code: crates/auth/src/jwt.rs:30-31 (ACCESS_TOKEN_TTL_SECS, doc comment "15 minutes")
  • Code: crates/auth/src/jwt.rs:78-79 (validate_token, Validation::new(Algorithm::HS256) with no explicit leeway)
  • Existing characterization test: expiry_leeway_is_60_seconds (crates/auth/src/jwt.rs:426-447) — pins the current 60s-leeway behavior with an explanatory comment noting that tightening it to leeway = 0 would require updating that test (per the project's "tests are immutable during refactoring, but a deliberate behavior change is not a refactor" convention).

Suspected area: crates/auth/src/jwt.rs::validate_token — either set validation.leeway = 0 (deliberate behavior change, needs the pinned test updated) or add an explicit .leeway(60) with a doc-comment update so the 15-minute claim is accurate about what it actually guarantees.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingverification-findingFinding from a verification run

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions