feat: implement AuthModule with authentication and RBAC features

Added AuthModule with services, controllers, and guards for authentication. Implements session management, role-based access control, 2FA, and DTOs for user login, registration, and token refresh.
This commit is contained in:
Mathis HERRIOT
2026-01-08 15:24:40 +01:00
parent 9406ed9350
commit 42805e371e
12 changed files with 509 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { getIronSession } from "iron-session";
import { CryptoService } from "../../crypto/crypto.service";
import { getSessionOptions, SessionData } from "../session.config";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private readonly cryptoService: CryptoService,
private readonly configService: ConfigService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
const session = await getIronSession<SessionData>(
request,
response,
getSessionOptions(this.configService.get("SESSION_PASSWORD") as string),
);
const token = session.accessToken;
if (!token) {
throw new UnauthorizedException();
}
try {
const payload = await this.cryptoService.verifyJwt(token);
request.user = payload;
} catch {
throw new UnauthorizedException();
}
return true;
}
}

View File

@@ -0,0 +1,28 @@
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { RbacService } from "../rbac.service";
@Injectable()
export class RolesGuard implements CanActivate {
constructor(
private reflector: Reflector,
private rbacService: RbacService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const requiredRoles = this.reflector.getAllAndOverride<string[]>("roles", [
context.getHandler(),
context.getClass(),
]);
if (!requiredRoles) {
return true;
}
const { user } = context.switchToHttp().getRequest();
if (!user) {
return false;
}
const userRoles = await this.rbacService.getUserRoles(user.sub);
return requiredRoles.some((role) => userRoles.includes(role));
}
}