import { SignJWT, jwtVerify, decodeJwt, type JWTPayload, } from "jose"; import { ADMIN_ROLE, JWT_EXPIRY_SECONDS, type AdminJwtPayload, } from "@/lib/constants/auth"; import { unauthorized } from "@/modules/auth/errors"; function getJwtSecret(): Uint8Array { const secret = process.env.JWT_SECRET; if (!secret) { throw new Error("JWT_SECRET 未配置"); } return new TextEncoder().encode(secret); } function toAdminPayload(payload: JWTPayload): AdminJwtPayload { if (typeof payload.sub !== "string" || payload.role !== ADMIN_ROLE) { throw unauthorized("无效的令牌载荷"); } return { sub: payload.sub, role: ADMIN_ROLE }; } /** 签发管理员 JWT */ export async function signToken(payload: AdminJwtPayload): Promise { return new SignJWT({ role: payload.role }) .setProtectedHeader({ alg: "HS256" }) .setSubject(payload.sub) .setIssuedAt() .setExpirationTime(`${JWT_EXPIRY_SECONDS}s`) .sign(getJwtSecret()); } /** 校验管理员 JWT,无效/过期/篡改抛 AuthError */ export async function verifyToken(token: string): Promise { try { const { payload } = await jwtVerify(token, getJwtSecret(), { algorithms: ["HS256"], }); return toAdminPayload(payload); } catch { throw unauthorized("令牌无效或已过期"); } } /** 解码 JWT(不校验签名,仅调试/解析) */ export function decodeToken(token: string): AdminJwtPayload | null { try { return toAdminPayload(decodeJwt(token)); } catch { return null; } }