import crypto from "crypto"; import { db } from "@/lib/db"; export const ACCESS_TOKEN_EXPIRES_IN = 15 * 60; export const REFRESH_TOKEN_EXPIRES_IN = 30 * 24 * 60 * 60; function addSeconds(seconds: number) { return new Date(Date.now() + seconds * 1000); } export function hashToken(token: string) { return crypto.createHash("sha256").update(token).digest("hex"); } export function generateToken() { return crypto.randomBytes(48).toString("base64url"); } export async function createMobileTokenPair(userId: string, refreshFamilyId?: string) { const accessToken = generateToken(); const refreshToken = generateToken(); const accessTokenExpiresAt = addSeconds(ACCESS_TOKEN_EXPIRES_IN); const refreshTokenExpiresAt = addSeconds(REFRESH_TOKEN_EXPIRES_IN); const session = await db.session.create({ data: { sessionToken: accessToken, userId, expires: accessTokenExpiresAt, }, }); const refreshSession = await db.refreshToken.create({ data: { tokenHash: hashToken(refreshToken), userId, familyId: refreshFamilyId ?? crypto.randomUUID(), expiresAt: refreshTokenExpiresAt, }, }); return { accessToken, accessTokenExpiresAt, refreshToken, refreshTokenExpiresAt, refreshTokenId: refreshSession.id, refreshFamilyId: refreshSession.familyId, sessionId: session.id, }; } export async function revokeRefreshTokenFamily(userId: string, familyId: string) { await db.refreshToken.updateMany({ where: { userId, familyId, revokedAt: null, }, data: { revokedAt: new Date(), }, }); }