feat(ST-1002): add pairing helpers, pre-auth cookie + paired-session guard
lib/auth/pairing.ts: pure crypto-helpers voor de QR-pairing flow. - generateMobileSecret() / generateDesktopToken() — beide 32 bytes base64url, los zodat ze elkaar niet onthullen - hashToken(t) — sha256-hex - verifyToken(t, hash) — timingSafeEqual met length-guard - isPairedSessionExpired(session) — geëxtraheerde helper zodat de Server- Component-render Date.now() niet rechtstreeks aanroept (React Compiler-flag) lib/auth/pair-cookie.ts: HttpOnly pre-auth cookie helpers (s4m_pair). - Path=/api/auth/pair, Max-Age=120s (gelijk aan pending-TTL pairing), SameSite=Lax, Secure in productie lib/session.ts: SessionData uitgebreid met optionele paired + pairedExpiresAt. app/(app)/layout.tsx: guard die paired-sessies vernietigt zodra pairedExpiresAt verstreken is en redirect naar /login. Tests: 14 unit-tests in __tests__/lib/auth/pairing.test.ts dekken hash- determinisme, timing-safe verify (true/false/length-mismatch), generator- uniciteit en vier expiry-scenario's voor isPairedSessionExpired. Quality gates: npm run lint (0 errors), tsc --noEmit clean, vitest 111/111. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
075cf28a5e
commit
b4813e6e54
5 changed files with 175 additions and 0 deletions
|
|
@ -3,6 +3,10 @@ import { SessionOptions } from 'iron-session'
|
|||
export interface SessionData {
|
||||
userId: string
|
||||
isDemo: boolean
|
||||
// ST-1002 (M10) — gezet door /api/auth/pair/claim na een succesvolle QR-pairing.
|
||||
// Beide velden zijn optioneel zodat bestaande wachtwoord-sessies onveranderd blijven.
|
||||
paired?: boolean
|
||||
pairedExpiresAt?: number // unix ms
|
||||
}
|
||||
|
||||
export const sessionOptions: SessionOptions = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue