Files
dashboard/backend/src/services/token.service.ts
Matthias Hochmeister 3c9b7d3446 apply security audit
2026-03-11 13:51:01 +01:00

125 lines
3.4 KiB
TypeScript

import jwt from 'jsonwebtoken';
import environment from '../config/environment';
import logger from '../utils/logger';
import { JwtPayload, RefreshTokenPayload } from '../types/auth.types';
class TokenService {
/**
* Generate JWT access token
*/
generateToken(payload: JwtPayload): string {
try {
const token = jwt.sign(
{
userId: payload.userId,
email: payload.email,
authentikSub: payload.authentikSub,
groups: payload.groups ?? [],
role: payload.role,
},
environment.jwt.secret,
{
expiresIn: environment.jwt.expiresIn as any,
}
);
logger.info('Generated JWT token', { userId: payload.userId });
return token;
} catch (error) {
logger.error('Failed to generate JWT token', { error });
throw new Error('Token generation failed');
}
}
/**
* Verify and decode JWT token
*/
verifyToken(token: string): JwtPayload {
try {
const decoded = jwt.verify(
token,
environment.jwt.secret
) as JwtPayload;
logger.debug('JWT token verified', { userId: decoded.userId });
return decoded;
} catch (error) {
if (error instanceof jwt.TokenExpiredError) {
logger.warn('JWT token expired');
throw new Error('Token expired');
} else if (error instanceof jwt.JsonWebTokenError) {
logger.warn('Invalid JWT token', { error: error.message });
throw new Error('Invalid token');
} else {
logger.error('Failed to verify JWT token', { error });
throw new Error('Token verification failed');
}
}
}
/**
* Generate refresh token (longer lived)
*/
generateRefreshToken(payload: RefreshTokenPayload): string {
try {
const token = jwt.sign(
{
userId: payload.userId,
email: payload.email,
},
environment.jwt.secret,
{
expiresIn: '7d', // Refresh tokens valid for 7 days
}
);
logger.info('Generated refresh token', { userId: payload.userId });
return token;
} catch (error) {
logger.error('Failed to generate refresh token', { error });
throw new Error('Refresh token generation failed');
}
}
/**
* Verify refresh token
*/
verifyRefreshToken(token: string): RefreshTokenPayload {
try {
const decoded = jwt.verify(
token,
environment.jwt.secret
) as RefreshTokenPayload;
logger.debug('Refresh token verified', { userId: decoded.userId });
return decoded;
} catch (error) {
if (error instanceof jwt.TokenExpiredError) {
logger.warn('Refresh token expired');
throw new Error('Refresh token expired');
} else if (error instanceof jwt.JsonWebTokenError) {
logger.warn('Invalid refresh token', { error: error.message });
throw new Error('Invalid refresh token');
} else {
logger.error('Failed to verify refresh token', { error });
throw new Error('Refresh token verification failed');
}
}
}
/**
* Decode token without verification (for debugging)
*/
decodeToken(token: string): JwtPayload | null {
try {
const decoded = jwt.decode(token) as JwtPayload;
return decoded;
} catch (error) {
logger.error('Failed to decode token', { error });
return null;
}
}
}
export default new TokenService();