import { SignJWT, jwtVerify } from 'jose'; import type { APIContext } from 'astro'; import { authEnv } from './env'; let secretCache: Uint8Array | null = null; function getSecret(): Uint8Array { if (!secretCache) { secretCache = new TextEncoder().encode(authEnv.JWT_SECRET); } return secretCache; } export async function createToken(userId: string): Promise { return new SignJWT({ sub: userId }) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() .setExpirationTime('7d') .sign(getSecret()); } export async function verifyToken(token: string): Promise<{ sub: string }> { const { payload } = await jwtVerify(token, getSecret(), { clockTolerance: 60, }); if (!payload.sub || typeof payload.sub !== 'string') { throw new Error('Invalid token payload'); } return { sub: payload.sub }; } export function setAuthCookie(token: string, context: APIContext): void { context.cookies.set('auth_token', token, { httpOnly: true, secure: true, sameSite: 'lax', maxAge: 60 * 60 * 24 * 7, path: '/', }); } export function clearAuthCookie(context: APIContext): void { context.cookies.delete('auth_token', { path: '/', }); }