import { jwtVerify } from "jose"; // Secret key for JWT verification (must match the one used for signing) const rawSecret = (process.env.JWT_SECRET ?? "").trim().replace(/^"|"$/g, ""); const JWT_SECRET = new TextEncoder().encode(rawSecret); export interface JWTPayload { email: string; role: string; iat: number; exp: number; MustChangePassword: boolean; Groups: string[]; } /** * Validates a JWT token and returns the payload if valid */ export async function validateToken(token: string): Promise { try { const raw = token.startsWith("Bearer ") ? token.slice(7) : token; const { payload } = await jwtVerify(raw, JWT_SECRET, { algorithms: ["HS256"], }); return payload as unknown as JWTPayload; } catch (error) { console.error("Token validation error:", error); return null; } } /** * Checks if a token is expired */ export function isTokenExpired(payload: JWTPayload): boolean { const currentTime = Math.floor(Date.now() / 1000); return payload.exp < currentTime; } /** * Gets token expiration time in a human-readable format */ export function getTokenExpirationTime(payload: JWTPayload): Date { return new Date(payload.exp * 1000); } /** * Gets time until token expires in seconds */ export function getTimeUntilExpiration(payload: JWTPayload): number { const currentTime = Math.floor(Date.now() / 1000); return Math.max(0, payload.exp - currentTime); } export function validatePassword(password: string) { const errors: string[] = []; if (password.length < 8) errors.push("At least 8 characters"); if (!/[A-Z]/.test(password)) errors.push("One uppercase letter"); if (!/[a-z]/.test(password)) errors.push("One lowercase letter"); if (!/[0-9]/.test(password)) errors.push("One number"); if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) errors.push("One special character"); return { valid: errors.length === 0, errors, }; }