3.2 KiB
3.2 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Implement Rate Limiting | HIGH | Protects against abuse and ensures fair resource usage | security, rate-limiting, throttler, protection |
Implement Rate Limiting
Use @nestjs/throttler to limit request rates per client. Apply different limits for different endpoints - stricter for auth endpoints, more relaxed for read operations. Consider using Redis for distributed rate limiting in clustered deployments.
Incorrect (no rate limiting on sensitive endpoints):
// No rate limiting on sensitive endpoints
@Controller('auth')
export class AuthController {
@Post('login')
async login(@Body() dto: LoginDto): Promise<TokenResponse> {
// Attackers can brute-force credentials
return this.authService.login(dto);
}
@Post('forgot-password')
async forgotPassword(@Body() dto: ForgotPasswordDto): Promise<void> {
// Can be abused to spam users with emails
return this.authService.sendResetEmail(dto.email);
}
}
// Same limits for all endpoints
@UseGuards(ThrottlerGuard)
@Controller('api')
export class ApiController {
@Get('public-data')
async getPublic() {} // Should allow more requests
@Post('process-payment')
async payment() {} // Should be more restrictive
}
Correct (configured throttler with endpoint-specific limits):
// Configure throttler globally with multiple limits
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
@Module({
imports: [
ThrottlerModule.forRoot([
{
name: 'short',
ttl: 1000, // 1 second
limit: 3, // 3 requests per second
},
{
name: 'medium',
ttl: 10000, // 10 seconds
limit: 20, // 20 requests per 10 seconds
},
{
name: 'long',
ttl: 60000, // 1 minute
limit: 100, // 100 requests per minute
},
]),
],
providers: [
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
],
})
export class AppModule {}
// Override limits per endpoint
@Controller('auth')
export class AuthController {
@Post('login')
@Throttle({ short: { limit: 5, ttl: 60000 } }) // 5 attempts per minute
async login(@Body() dto: LoginDto): Promise<TokenResponse> {
return this.authService.login(dto);
}
@Post('forgot-password')
@Throttle({ short: { limit: 3, ttl: 3600000 } }) // 3 per hour
async forgotPassword(@Body() dto: ForgotPasswordDto): Promise<void> {
return this.authService.sendResetEmail(dto.email);
}
}
// Skip throttling for certain routes
@Controller('health')
export class HealthController {
@Get()
@SkipThrottle()
check(): string {
return 'OK';
}
}
// Custom throttle per user type
@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
protected async getTracker(req: Request): Promise<string> {
// Use user ID if authenticated, IP otherwise
return req.user?.id || req.ip;
}
protected async getLimit(context: ExecutionContext): Promise<number> {
const request = context.switchToHttp().getRequest();
// Higher limits for authenticated users
if (request.user) {
return request.user.isPremium ? 1000 : 200;
}
return 50; // Anonymous users
}
}
Reference: NestJS Throttler