import { SignJWT, jwtVerify, type JWTPayload } from "jose"; import { JWT_EXPIRY_SECONDS } from "@/lib/constants/auth"; import { unauthorized } from "@/modules/auth/errors"; export const EMBED_DEMO_ROLE = "embed_demo" as const; export const EMBED_DEMO_COOKIE = "embed_demo_session"; export const EMBED_DEMO_DEFAULT_PASSWORD = "123456"; export type EmbedDemoJwtPayload = { sub: string; role: typeof EMBED_DEMO_ROLE; }; function getJwtSecret(): Uint8Array { const secret = process.env.JWT_SECRET; if (!secret) { throw new Error("JWT_SECRET 未配置"); } return new TextEncoder().encode(secret); } export function getEmbedDemoPassword(): string { return process.env.EMBED_DEMO_PASSWORD?.trim() || EMBED_DEMO_DEFAULT_PASSWORD; } function toEmbedPayload(payload: JWTPayload): EmbedDemoJwtPayload { if (typeof payload.sub !== "string" || payload.role !== EMBED_DEMO_ROLE) { throw unauthorized("无效的演示会话"); } return { sub: payload.sub, role: EMBED_DEMO_ROLE }; } export async function signEmbedDemoToken(customerId: string): Promise { return new SignJWT({ role: EMBED_DEMO_ROLE }) .setProtectedHeader({ alg: "HS256" }) .setSubject(customerId) .setIssuedAt() .setExpirationTime(`${JWT_EXPIRY_SECONDS}s`) .sign(getJwtSecret()); } export async function verifyEmbedDemoToken( token: string, ): Promise { try { const { payload } = await jwtVerify(token, getJwtSecret(), { algorithms: ["HS256"], }); return toEmbedPayload(payload); } catch { throw unauthorized("演示会话无效或已过期"); } }