65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
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(),
|
|
},
|
|
});
|
|
}
|