feat(02-01): AuthModule with Passport strategies, guards, and decorators

- Create LocalStrategy (username/password via argon2) and JwtStrategy (cookie extractor)
- Create JwtAuthGuard with @Public() decorator support for route opt-out
- Create RolesGuard checking SUPER_ADMIN/ADMIN/USER roles per D-12
- Create AuthService with validateUser, login (30-day httpOnly cookie), logout
- Create AuthController with POST /auth/login, POST /auth/logout, GET /auth/me
- Create LoginDto with class-validator decorators
- Create @Public, @Roles, @CurrentUser decorators
- Update main.ts with ValidationPipe, CORS credentials, cookie-parser
- Install cookie-parser for httpOnly JWT cookie support
This commit is contained in:
2026-06-18 13:24:59 +02:00
parent d0b36c8f22
commit 6190f3dd39
14 changed files with 358 additions and 1 deletions
@@ -0,0 +1,35 @@
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-jwt';
import { Request } from 'express';
/**
* Custom extractor that reads JWT from the httpOnly "session" cookie.
*/
function cookieExtractor(req: Request): string | null {
if (req && req.cookies) {
return req.cookies['session'] || null;
}
return null;
}
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(configService: ConfigService) {
super({
jwtFromRequest: cookieExtractor,
ignoreExpiration: false,
secretOrKey: configService.get<string>('JWT_SECRET', 'fallback-secret'),
});
}
async validate(payload: any) {
return {
id: payload.sub,
username: payload.username,
role: payload.role,
tenantId: payload.tenantId,
};
}
}