homeio
PublicForked from doctor-io/homeio
session-token.ts
import "server-only";
import { createHmac, timingSafeEqual } from "node:crypto";
import { serverEnv } from "@/lib/server/env";
import {
buildSessionPayload,
isSessionExpired,
parseSessionToken,
} from "@/lib/shared/auth/session";
function signPayload(payload: string) {
return createHmac("sha256", serverEnv.AUTH_SESSION_SECRET)
.update(payload)
.digest("hex");
}
export function createSessionToken(
sessionId: string,
expiresAtEpochSeconds: number,
) {
const payload = buildSessionPayload(sessionId, expiresAtEpochSeconds);
const signature = signPayload(payload);
return `${payload}.${signature}`;
}
export function verifySessionToken(token: string) {
const parsed = parseSessionToken(token);
if (!parsed) return null;
if (isSessionExpired(parsed.expiresAtEpochSeconds)) return null;
const expectedSignature = signPayload(parsed.payload);
const expectedBuffer = Buffer.from(expectedSignature, "utf8");
const actualBuffer = Buffer.from(parsed.signature, "utf8");
if (expectedBuffer.length !== actualBuffer.length) return null;
if (!timingSafeEqual(expectedBuffer, actualBuffer)) return null;
return {
sessionId: parsed.sessionId,
expiresAtEpochSeconds: parsed.expiresAtEpochSeconds,
};
}