Skip to content

Add server-side session records with expiry and rotation for SEP-10 auth - #834

Open
gadst12 wants to merge 1 commit into
scout-off:mainfrom
gadst12:feature/sep10-session-expiry-rotation-660
Open

Add server-side session records with expiry and rotation for SEP-10 auth#834
gadst12 wants to merge 1 commit into
scout-off:mainfrom
gadst12:feature/sep10-session-expiry-rotation-660

Conversation

@gadst12

@gadst12 gadst12 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #660
app/api/auth/sep10/route.ts set the session cookie (response.cookies.set('session', publicKey, ...)) with no maxAge/expires, so once a wallet completed SEP-10 verification the resulting session was valid indefinitely until the browser hit the DELETE handler. There was also no server-side session record at all — the cookie's raw value was the identity, with nothing to revoke server-side beyond deleting that exact cookie — and /api/auth/session GET trusted any present cookie value with no expiry check.

Changes

  • lib/sessionStore.ts (new): a lightweight file-backed session store (mirrors the existing lib/referralStore.ts pattern) holding { id, publicKey, createdAt, expiresAt, revoked } records, with createSession, getValidSession, revokeSession, and renewSession (rotation: issues a fresh id/expiry and revokes the old one).
  • app/api/auth/sep10/route.ts:
    • POST now creates a server-side session record on successful verification and sets the session cookie to an opaque session id (not the raw public key) with a bounded maxAge (SESSION_MAX_AGE_SECONDS env var, default 24h).
    • DELETE now revokes the session record server-side in addition to clearing the cookie.
  • app/api/auth/session/route.ts:
    • GET now resolves the cookie through getValidSession and rejects expired/revoked sessions with 401, instead of trusting any present cookie value.
    • New PUT handler rotates an active session to a fresh id/expiry (renewal), so long-lived users aren't abruptly logged out — returns 401 and clears the cookie if the session can no longer be renewed.
  • Referral routes (generate, redeem, count): previously read the raw cookie value and used it directly as the wallet address. Since the cookie is now an opaque session id, these routes resolve the actual public key via getValidSession first.
  • .env.example: documents the new SESSION_MAX_AGE_SECONDS var (required by the repo's validate-env.js check).
  • Tests: extended __tests__/api/auth/sep10/route.test.ts and __tests__/api/auth/session/route.test.ts to cover session creation/cookie shape, revocation, expiry, and rotation; added __tests__/lib/sessionStore.test.ts covering the store's expiry/revocation/rotation semantics directly.

Test plan

  • npx jest __tests__/api/auth __tests__/lib/sessionStore.test.ts — all passing
  • npx eslint on all changed files — clean
  • npx prettier --check on all changed files — clean
  • node scripts/validate-env.js — passes with the new env var declared
  • Confirmed no new tsc --noEmit errors introduced by this diff (pre-existing unrelated errors on main untouched)

The session cookie previously held the wallet public key directly with no
maxAge, so a completed SEP-10 verification produced a session valid
forever with no server-side way to revoke it short of the browser
deleting its own cookie.

- lib/sessionStore.ts: file-backed session records (id, publicKey,
  createdAt, expiresAt, revoked) with createSession/getValidSession/
  revokeSession/renewSession
- sep10 route now issues an opaque session id (not the raw public key)
  with a bounded maxAge (SESSION_MAX_AGE_SECONDS, default 24h), and its
  DELETE handler revokes the record server-side in addition to clearing
  the cookie
- /api/auth/session GET now rejects expired/revoked sessions instead of
  trusting any cookie value, and a new PUT handler rotates an active
  session to a fresh id/expiry so long sessions can renew without
  dropping the user
- referral routes now resolve the wallet address via the session record
  instead of assuming the cookie value is the address
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add expiration and rotation to the SEP-10 session cookie

1 participant