/
goncharovchik
/
secure-api-d
Обзор
Документация
Войти
/
goncharovchik
/
secure-api-d
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/modules/auth/auth.controller.ts
90 строк
3 KB
Aleksey Goncharov
feat: secure API with 26 OWASP security measures
29 апр 2026, 13:30
29 апр 2026, 13:30
449fe34
Код
Авторство
О чём код?
import { Controller, Post, Body, Res, HttpCode, HttpStatus } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; import type { Response } from 'express'; import { AuthService } from './auth.service'; import { LoginDto } from './dto/login.dto'; import { RegisterDto } from './dto/register.dto'; import { RefreshTokenDto } from './dto/refresh-token.dto'; import { Public } from '../../common/decorators/public.decorator'; import { CurrentUser } from '../../common/decorators/current-user.decorator'; /** * Контроллер аутентификации. * Мера #1: JWT Auth, #2: bcrypt, #4: Password Policy, #5: Token Rotation, #15: Secure Cookies. */ @ApiTags('Auth') @Controller('api/auth') export class AuthController { constructor(private readonly authService: AuthService) {} @Public() @Post('register') @ApiOperation({ summary: 'Регистрация нового пользователя' }) async register(@Body() dto: RegisterDto, @Res({ passthrough: true }) res: Response) { const result = await this.authService.register(dto); // Мера #15: Secure Cookie для refresh token this.setRefreshTokenCookie(res, result.refreshToken); return { message: result.message, user: result.user, accessToken: result.accessToken, }; } @Public() @Post('login') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Вход в систему' }) async login(@Body() dto: LoginDto, @Res({ passthrough: true }) res: Response) { const result = await this.authService.login(dto); // Мера #15: Secure Cookie для refresh token this.setRefreshTokenCookie(res, result.refreshToken); return { message: result.message, user: result.user, accessToken: result.accessToken, }; } @Public() @Post('refresh') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Обновить токены (Token Rotation)' }) async refresh(@Body() dto: RefreshTokenDto, @Res({ passthrough: true }) res: Response) { const result = await this.authService.refresh(dto.refreshToken); // Мера #15: Secure Cookie this.setRefreshTokenCookie(res, result.refreshToken); return { accessToken: result.accessToken }; } @Post('logout') @ApiBearerAuth() @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Выход из системы' }) async logout(@CurrentUser('id') userId: number, @Res({ passthrough: true }) res: Response) { res.clearCookie('refreshToken'); return this.authService.logout(userId); } /** * Мера #15: Secure Cookies. * httpOnly — недоступен из JavaScript. * secure — отправляется только по HTTPS. * sameSite — защита от CSRF. */ private setRefreshTokenCookie(res: Response, token: string) { res.cookie('refreshToken', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', maxAge: 7 * 24 * 60 * 60 * 1000, // 7 дней path: '/api/auth', }); } }