Fix session lifetime: 2h sliding idle timeout, not 30 days
The JWT's exp claim says 30 days, and I took that as the session
lifetime. It is only an outer ceiling. The server also keeps a per-token
whitelist entry in Valkey (jwt:{accountId}:{jti}) whose TTL is
JWT_TIMEOUT_SECONDS — 7200s on this instance — and JwtStrategy.validate
re-sets it on every authenticated request. Two hours idle and the token
is rejected with 29 days still on exp.
Proven, not inferred: the token from yesterday returned 401 at 13.8h old.
The live instance publishes the values unauthenticated at
GET /api/v3/config/public — JWT_TIMEOUT_SECONDS 7200,
JWT_SHOW_TIMEOUT_WARNING_SECONDS 3600, the latter being exactly the
one-hour UI prompt that prompted this investigation.
refresh-session turns out not to be special: it extends through the same
guard as any other route, and uniquely only in returning the remaining
TTL. So the keepalive uses GET /api/v3/me instead, and the server stays
GET-only; the one POST in the repo is in scripts/probe.mjs, where it
reports the idle budget.
JWT_EXTENDED_TIMEOUT_SECONDS (~1 month) exists in the config schema but
is vestigial: privateDevice has no references in the current NestJS
source, and generateJwtAndAddToWhitelist never overrides the TTL.
Also fixes a real breakage this surfaced: TypeScript parameter
properties are rejected by Node's type stripping, so `npm run dev` and
`npm test` both failed on any file reaching them. Rewritten as explicit
fields, and noted in CLAUDE.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
10
.env.example
10
.env.example
@@ -6,7 +6,9 @@
|
||||
TSC_URL=https://schulcloud-thueringen.de
|
||||
|
||||
# The value of the `jwt` cookie from a logged-in browser session.
|
||||
# Valid for 30 days from issue; see docs/AUTH.md for how to copy a fresh one.
|
||||
# Two clocks apply: a 30-day hard expiry, and a 2-hour idle timeout that every
|
||||
# API call resets. The built-in keepalive handles the second one, so in practice
|
||||
# this needs replacing monthly. See docs/AUTH.md.
|
||||
TSC_JWT_COOKIE=
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -36,3 +38,9 @@ BIND_HOST=0.0.0.0
|
||||
|
||||
# Per-request timeout against the Schulcloud API, in ms. Default 30000.
|
||||
# REQUEST_TIMEOUT_MS=30000
|
||||
|
||||
# How often to ping Schulcloud to hold the session open, in ms. Default 1800000
|
||||
# (30 min). Must stay well under the instance's JWT_TIMEOUT_SECONDS — 7200s
|
||||
# here, readable from GET /api/v3/config/public. Set to 0 to disable, which
|
||||
# will let the token die after two hours of inactivity.
|
||||
# KEEPALIVE_INTERVAL_MS=1800000
|
||||
|
||||
Reference in New Issue
Block a user