@@ -140,11 +140,14 @@ export class AuthService {
|
||||
const expiresIn = Number(this.config.get('RAYLAB_JWT_EXPIRES_IN') || 3600);
|
||||
const access = this.jwtService.sign(jwtPayload, { expiresIn });
|
||||
|
||||
logger.debug(`Created internal access token for user=${domainUser.id} expiresIn=${expiresIn}`);
|
||||
|
||||
// create internal refresh token
|
||||
const refreshToken = crypto.randomUUID();
|
||||
const refreshTtl = Number(this.config.get('RAYLAB_REFRESH_EXPIRES_IN') || 30 * 24 * 3600); // default 30 days
|
||||
|
||||
await this.refreshStore.set(refreshToken, { userId: domainUser.id }, refreshTtl);
|
||||
logger.debug(`Stored refresh token for user=${domainUser.id} ttl=${refreshTtl}`);
|
||||
|
||||
return {
|
||||
accessToken: access,
|
||||
@@ -162,9 +165,16 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async refresh(refreshToken?: string) {
|
||||
if (!refreshToken) throw new UnauthorizedException('Missing refresh token');
|
||||
if (!refreshToken) {
|
||||
logger.debug('Refresh called without refresh token');
|
||||
throw new UnauthorizedException('Missing refresh token');
|
||||
}
|
||||
const data = await this.refreshStore.get(refreshToken);
|
||||
if (!data) throw new UnauthorizedException('Invalid refresh token');
|
||||
if (!data) {
|
||||
logger.debug(`Refresh token not found or expired: ${refreshToken}`);
|
||||
throw new UnauthorizedException('Invalid refresh token');
|
||||
}
|
||||
logger.debug(`Refresh token validated for userId=${data.userId}`);
|
||||
|
||||
const userId = data.userId;
|
||||
// load user
|
||||
@@ -177,9 +187,11 @@ export class AuthService {
|
||||
const newRefresh = crypto.randomUUID();
|
||||
const refreshTtl = Number(this.config.get('RAYLAB_REFRESH_EXPIRES_IN') || 30 * 24 * 3600);
|
||||
await this.refreshStore.set(newRefresh, { userId }, refreshTtl);
|
||||
logger.debug(`Rotated refresh token for userId=${userId} newRefresh=${newRefresh} ttl=${refreshTtl}`);
|
||||
|
||||
const expiresIn = Number(this.config.get('RAYLAB_JWT_EXPIRES_IN') || 3600);
|
||||
const access = this.jwtService.sign({ sub: domainUser.id, preferred_username: domainUser.username, email: domainUser.email }, { expiresIn });
|
||||
logger.debug(`Issued new access token for user=${userId} expiresIn=${expiresIn}`);
|
||||
|
||||
return { accessToken: access, refreshToken: newRefresh, expiresIn, refreshTtl };
|
||||
}
|
||||
@@ -204,13 +216,18 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async me(token?: string) {
|
||||
if (!token) throw new UnauthorizedException('Missing token');
|
||||
if (!token) {
|
||||
logger.debug('Me called without token');
|
||||
throw new UnauthorizedException('Missing token');
|
||||
}
|
||||
try {
|
||||
const payload: any = this.jwtService.verify(token);
|
||||
logger.debug(`Token verified successfully. payload.sub=${payload.sub}`);
|
||||
const user = await this.userRepository.getById(payload.sub);
|
||||
if (!user) throw new UnauthorizedException('User not found');
|
||||
return { id: user.id, username: user.username, email: user.email, roles: user.roles || [] };
|
||||
} catch (e) {
|
||||
logger.debug(`Token verification failed: ${(e as Error).message}`);
|
||||
throw new UnauthorizedException('Invalid token');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user