Scrum4Me/lib/auth/pair-cookie.ts
Madhura68 c48e30df1f fix(M10): bump pending-TTL to 5min + repair MD3 contrast on pair page
TTL: 2 min was te kort voor handmatig curl-paste-confirm-testen — gebruiker
zag 'Pairing verlopen' voor hij kon bevestigen. Bumpt naar 5 min (gelijk aan
approved-TTL): nog steeds tight voor security, ruim voor menselijke reactie.
- app/api/auth/pair/start/route.ts: PENDING_TTL_MS 120s → 300s
- lib/auth/pair-cookie.ts: MAX_AGE_SECONDS 120 → 300
- __tests__/api/pair-start.test.ts: maxAge en expires_at-window meegegroeid

Kleuren: bevestigingspagina gebruikte bg-destructive/10 + text-destructive-
foreground — beide lichte kleuren, te weinig contrast. Vervangen door MD3
container-tokens (zelfde patroon als components/auth/auth-form.tsx):
- error-state: bg-error-container + text-error-container-foreground + border-l-4 border-error
- approved-state: bg-success-container + foreground + accent-border
- cancelled-state: bg-surface-container-high + neutral foreground

Quality gates: lint 0 errors, tsc clean, vitest 139/139.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:15:02 +02:00

33 lines
1.1 KiB
TypeScript

// ST-1002: HttpOnly pre-auth cookie voor de QR-pairing desktop-side.
//
// Wordt gezet door /api/auth/pair/start (ST-1003), gelezen door
// /api/auth/pair/stream/[id] (ST-1004) en /api/auth/pair/claim (ST-1006),
// en gewist op claim of cancel. Path-scoped naar /api/auth/pair zodat de
// cookie niet naar andere routes lekt.
import { cookies } from 'next/headers'
const COOKIE_NAME = 's4m_pair'
const MAX_AGE_SECONDS = 300 // gelijk aan pending-TTL van LoginPairing (5 min)
const COOKIE_PATH = '/api/auth/pair'
export async function setPairCookie(desktopToken: string): Promise<void> {
const jar = await cookies()
jar.set(COOKIE_NAME, desktopToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: COOKIE_PATH,
maxAge: MAX_AGE_SECONDS,
})
}
export async function readPairCookie(): Promise<string | null> {
const jar = await cookies()
return jar.get(COOKIE_NAME)?.value ?? null
}
export async function clearPairCookie(): Promise<void> {
const jar = await cookies()
jar.delete({ name: COOKIE_NAME, path: COOKIE_PATH })
}