-
Notifications
You must be signed in to change notification settings - Fork 0
Security Documentation ‐ HelloKitchen API
The HelloKitchen API uses a secure architecture based on NestJS with multiple protection layers:
- Global input validation
- Protection against common attacks with Helmet
- Rate limiting to prevent brute force attacks
- JWT for authentication
const app = await NestFactory.create(AppModule, { abortOnError: false });
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // Remove undefined properties in the DTO
forbidNonWhitelisted: true, // Throw an error if undefined properties are present
transform: true, // Transform the values according to the type specified in the DTO
}),
);
app.use(helmet());
app.use(
rateLimit({
windowMs: 15 * 60 * 1000, // 15 min
max: 100, // IP Limit
}),
);The application implements several essential security middlewares:
- Helmet : HTTP headers protection
- Rate Limiting : 100 requests per IP on 15 minutes
- Validation Pipe : Cleaning and validating incoming data
The login system is managed by the login module:
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
global: true,
signOptions: { expiresIn: '1h' }, // life of the token
secret: 'secret',
}),
],
controllers: [
LoginController /**< The controller responsible for handling HTTP requests related to login items */,
],
providers: [
LoginService /**< The service that contains the business logic for managing login items */,
JwtStrategy,
],
exports: [JwtModule, PassportModule],
})The JWT strategy is configured for maximum security:
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'secret',
});
}
}The JWT guard protects sensitive routes:
@Injectable()
export class AuthGuard extends AuthGuard('jwt') {}Le modèle de données utilisateur définit la structure sécurisée :
@Prop({
type: Number,
required: true,
description: 'Must be an integer and is required',
})
id: number;
@Prop({ type: Number, required: true, description: 'Must be an integer' })
id_restaurant: number;
@Prop({
type: String,
required: true,
description: 'Must be a string',
})
username: string;
@Prop({
type: String,
required: true,
description: 'Must be a string',
})
password: string;Example of validation in the restaurant controller:
@Post()
@UseGuards(AuthGuard)
@UsePipes(ValidationPipe)The tests check the security of the authentication process:
describe('login', () => {
const loginCredentials = {
username: 'testuser',
password: 'testpass',
idRestaurant: 1,
};
const mockUser = {
id: 1,
username: 'testuser',
role: 'user',
};
const mockToken = {
access_token: 'mock.jwt.token',
};
it('should successfully authenticate and return a token', async () => {
mockLoginService.authenticateUser.mockResolvedValue(mockUser);
mockLoginService.login.mockResolvedValue(mockToken);
const result = await controller.login(
loginCredentials.password,
loginCredentials.username,
loginCredentials.idRestaurant,
);
expect(mockLoginService.authenticateUser).toHaveBeenCalledWith(
loginCredentials.idRestaurant,
loginCredentials.username,
loginCredentials.password,
);
expect(mockLoginService.login).toHaveBeenCalledWith(mockUser);
expect(result).toEqual(mockToken);
});
it('should throw BadRequestException when authentication fails', async () => {
mockLoginService.authenticateUser.mockRejectedValue(
new BadRequestException(),
);
await expect(
controller.login(
loginCredentials.password,
loginCredentials.username,
loginCredentials.idRestaurant,
),
).rejects.toThrow(BadRequestException);
});-
Securing Secrets
- Move secrets to environment variables
- Use a secrets manager (ex: Vault)
-
Strengthening Authentication
- Implement password hashing
- Add a refresh tokens system
- Implement a strong password policy
-
Logging and Monitoring
- Implement a secure logging system
- Set up monitoring of authentication attempts
- Configure security alerts
Add to the .env file:
JWT_SECRET=your_complex_secret
JWT_EXPIRATION=3600
MONGODB_URI=your_mongodb_uri
RATE_LIMIT_MAX=100
RATE_LIMIT_WINDOW=900000
-
Data Validation
- Use DTOs systematically
- Validate all user inputs
- Escape sensitive data
-
Error Management
- Do not expose technical details in error messages
- Log security errors
- Implement centralized error management
-
Tests
- Maintain a high test coverage
- Include security tests
- Test error cases
This security documentation should be regularly updated and shared with the development team. The recommendations should be implemented according to their priority to maintain an optimal security level.