- Updated `next.config.js` in both web-admin and web-client to enable React strict mode, set output to standalone, and expose environment variables for API URL. - Enhanced `auth-sdk` with detailed comments for JWT verification, decoding, and token management functions. - Improved `http-client` with comprehensive documentation for HTTP client configuration and methods. - Expanded `logger` functionality with detailed configuration options and logging formats. - Enhanced `tracing` setup with detailed comments for distributed tracing configuration. - Updated `types` definitions for authentication and user data transfer objects with comprehensive comments. - Improved `auth-service` with detailed comments in controllers, services, and middlewares for better clarity and maintainability. - Added health check endpoints in `health.controller.ts` for service monitoring. - Enhanced error handling and logging throughout the application for better debugging and user feedback.
130 lines
4.6 KiB
TypeScript
130 lines
4.6 KiB
TypeScript
import * as jwt from 'jsonwebtoken';
|
|
import type { SignOptions } from 'jsonwebtoken';
|
|
import { TokenPayload } from '@goodgo/types';
|
|
|
|
/**
|
|
* EN: Options for JWT token verification
|
|
* VI: Tùy chọn cho việc xác minh JWT token
|
|
*/
|
|
export interface VerifyTokenOptions {
|
|
/** EN: Secret key used to verify the token / VI: Khóa bí mật dùng để xác minh token */
|
|
secret: string;
|
|
/** EN: Whether to ignore token expiration / VI: Có bỏ qua việc hết hạn token không */
|
|
ignoreExpiration?: boolean;
|
|
}
|
|
|
|
/**
|
|
* EN: Verify and decode a JWT token
|
|
* VI: Xác minh và giải mã JWT token
|
|
*
|
|
* @param token - JWT token string to verify / Chuỗi JWT token cần xác minh
|
|
* @param options - Verification options / Tùy chọn xác minh
|
|
* @returns Decoded token payload / Payload đã giải mã
|
|
* @throws Error if token is invalid or expired / Lỗi nếu token không hợp lệ hoặc hết hạn
|
|
*/
|
|
export const verifyToken = (token: string, options: VerifyTokenOptions): TokenPayload => {
|
|
try {
|
|
// EN: Verify token signature and decode payload
|
|
// VI: Xác minh chữ ký token và giải mã payload
|
|
const decoded = jwt.verify(token, options.secret, {
|
|
ignoreExpiration: options.ignoreExpiration || false,
|
|
}) as TokenPayload;
|
|
return decoded;
|
|
} catch (error) {
|
|
throw new Error('Invalid or expired token / Token không hợp lệ hoặc hết hạn');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* EN: Decode JWT token without verification (for inspection only)
|
|
* VI: Giải mã JWT token mà không xác minh (chỉ để kiểm tra)
|
|
*
|
|
* @param token - JWT token string to decode / Chuỗi JWT token cần giải mã
|
|
* @returns Decoded token payload or null if invalid / Payload đã giải mã hoặc null nếu không hợp lệ
|
|
*/
|
|
export const decodeToken = (token: string): TokenPayload | null => {
|
|
try {
|
|
// EN: Decode token without signature verification
|
|
// VI: Giải mã token mà không xác minh chữ ký
|
|
return jwt.decode(token) as TokenPayload;
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* EN: Create a new JWT token with payload and expiration
|
|
* VI: Tạo JWT token mới với payload và thời gian hết hạn
|
|
*
|
|
* @param payload - Token payload data (without iat/exp) / Dữ liệu payload token (không có iat/exp)
|
|
* @param secret - Secret key for signing / Khóa bí mật để ký
|
|
* @param expiresIn - Token expiration time (default: 15m) / Thời gian hết hạn token (mặc định: 15m)
|
|
* @returns Signed JWT token string / Chuỗi JWT token đã ký
|
|
*/
|
|
export const createToken = (
|
|
payload: Omit<TokenPayload, 'iat' | 'exp'>,
|
|
secret: string,
|
|
expiresIn: string = '15m'
|
|
): string => {
|
|
// EN: Sign payload with secret and expiration
|
|
// VI: Ký payload với secret và thời gian hết hạn
|
|
return jwt.sign(payload, secret, { expiresIn } as SignOptions);
|
|
};
|
|
|
|
/**
|
|
* EN: Check if JWT token has expired
|
|
* VI: Kiểm tra JWT token đã hết hạn chưa
|
|
*
|
|
* @param token - JWT token string to check / Chuỗi JWT token cần kiểm tra
|
|
* @returns True if token is expired or invalid / True nếu token đã hết hạn hoặc không hợp lệ
|
|
*/
|
|
export const isTokenExpired = (token: string): boolean => {
|
|
try {
|
|
// EN: Decode token and check expiration timestamp
|
|
// VI: Giải mã token và kiểm tra timestamp hết hạn
|
|
const decoded = decodeToken(token);
|
|
if (!decoded || !decoded.exp) {
|
|
return true;
|
|
}
|
|
// EN: Compare expiration time with current time
|
|
// VI: So sánh thời gian hết hạn với thời gian hiện tại
|
|
return decoded.exp * 1000 < Date.now();
|
|
} catch {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* EN: Extract JWT token from Authorization header (Bearer format)
|
|
* VI: Trích xuất JWT token từ header Authorization (định dạng Bearer)
|
|
*
|
|
* @param authHeader - Authorization header value / Giá trị header Authorization
|
|
* @returns JWT token string or null if invalid format / Chuỗi JWT token hoặc null nếu định dạng không hợp lệ
|
|
*/
|
|
export const extractTokenFromHeader = (authHeader: string | undefined): string | null => {
|
|
// EN: Return null if header is missing
|
|
// VI: Trả về null nếu header bị thiếu
|
|
if (!authHeader) {
|
|
return null;
|
|
}
|
|
|
|
// EN: Split header into parts (expected: "Bearer <token>")
|
|
// VI: Chia header thành các phần (mong đợi: "Bearer <token>")
|
|
const parts = authHeader.split(' ');
|
|
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
|
return null;
|
|
}
|
|
|
|
return parts[1];
|
|
};
|
|
|
|
// EN: Default export with all authentication utilities
|
|
// VI: Export default với tất cả các utility xác thực
|
|
export default {
|
|
verifyToken,
|
|
decodeToken,
|
|
createToken,
|
|
isTokenExpired,
|
|
extractTokenFromHeader,
|
|
};
|