49 lines
1.0 KiB
TypeScript
49 lines
1.0 KiB
TypeScript
import bcrypt from 'bcrypt';
|
|
import jwt from 'jsonwebtoken';
|
|
|
|
const SALT_ROUNDS = 10;
|
|
|
|
function getJwtSecret(): string {
|
|
const secret = process.env.JWT_SECRET;
|
|
if (!secret) {
|
|
throw new Error('JWT_SECRET is not set');
|
|
}
|
|
return secret;
|
|
}
|
|
|
|
/**
|
|
* Hash a password using bcrypt
|
|
*/
|
|
export async function hashPassword(password: string): Promise<string> {
|
|
return bcrypt.hash(password, SALT_ROUNDS);
|
|
}
|
|
|
|
/**
|
|
* Verify a password against a hash
|
|
*/
|
|
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
|
|
return bcrypt.compare(password, hash);
|
|
}
|
|
|
|
/**
|
|
* Generate a JWT token for a user
|
|
*/
|
|
export function generateToken(userId: string): string {
|
|
return jwt.sign({ userId }, getJwtSecret(), {
|
|
expiresIn: '7d'
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Verify and decode a JWT token
|
|
* Returns the user ID if valid, null otherwise
|
|
*/
|
|
export function verifyToken(token: string): { userId: string } | null {
|
|
try {
|
|
const decoded = jwt.verify(token, getJwtSecret()) as { userId: string };
|
|
return decoded;
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
}
|