Files
pagodera/lib/auth/jwt.ts
T
Evandro Fonseca Junior 55eebde0ba feat: add user authentication UI to header component
Add login and register dialogs, user dropdown menu with profile link and logout option, and integrate with session management hook. Prevent hydration mismatches by conditionally rendering auth elements after mount. Update package-lock.json with new @esbuild dependencies for build tooling.
2025-11-04 02:33:29 -03:00

134 lines
2.6 KiB
TypeScript

/**
* Módulo de geração e validação de tokens JWT
* Access tokens (15min) e Refresh tokens (7 dias)
*/
import jwt from "jsonwebtoken";
interface TokenPayload {
userId: number;
username: string;
type: "access" | "refresh";
}
/**
* Obtém o secret do JWT (lazy loading)
*/
function getJWTSecret(): string {
const secret = process.env.JWT_SECRET;
if (!secret) {
throw new Error("JWT_SECRET não está definido nas variáveis de ambiente");
}
return secret;
}
/**
* Obtém o refresh secret do JWT (lazy loading)
*/
function getJWTRefreshSecret(): string {
const secret = process.env.JWT_REFRESH_SECRET;
if (!secret) {
throw new Error(
"JWT_REFRESH_SECRET não está definido nas variáveis de ambiente"
);
}
return secret;
}
// Tempos de expiração
const ACCESS_TOKEN_EXPIRY = "15m"; // 15 minutos
const REFRESH_TOKEN_EXPIRY = "7d"; // 7 dias
/**
* Gera access token JWT
* @param userId - ID do usuário
* @param username - Nome de usuário
* @returns Access token
*/
export function generateAccessToken(
userId: number,
username: string
): string {
const payload: TokenPayload = {
userId,
username,
type: "access",
};
return jwt.sign(payload, getJWTSecret(), {
expiresIn: ACCESS_TOKEN_EXPIRY,
});
}
/**
* Gera refresh token JWT
* @param userId - ID do usuário
* @param username - Nome de usuário
* @returns Refresh token
*/
export function generateRefreshToken(
userId: number,
username: string
): string {
const payload: TokenPayload = {
userId,
username,
type: "refresh",
};
return jwt.sign(payload, getJWTRefreshSecret(), {
expiresIn: REFRESH_TOKEN_EXPIRY,
});
}
/**
* Valida e decodifica access token
* @param token - Access token
* @returns Payload do token ou null se inválido
*/
export function verifyAccessToken(token: string): {
userId: number;
username: string;
} | null {
try {
const decoded = jwt.verify(token, getJWTSecret()) as TokenPayload;
if (decoded.type !== "access") {
return null;
}
return {
userId: decoded.userId,
username: decoded.username,
};
} catch (error) {
return null;
}
}
/**
* Valida e decodifica refresh token
* @param token - Refresh token
* @returns Payload do token ou null se inválido
*/
export function verifyRefreshToken(token: string): {
userId: number;
username: string;
} | null {
try {
const decoded = jwt.verify(token, getJWTRefreshSecret()) as TokenPayload;
if (decoded.type !== "refresh") {
return null;
}
return {
userId: decoded.userId,
username: decoded.username,
};
} catch (error) {
return null;
}
}