OpenAPI
Security
Document authentication and authorization in your API
API Security
Document authentication and authorization requirements in your OpenAPI specification.
Security Schemes
Define security schemes in your OpenAPI configuration:
Bearer Authentication (JWT)
const config = new DocumentBuilder()
.setTitle('My API')
.setVersion('1.0')
.addBearerAuth({
name: 'JWT',
description: 'JWT Authorization header using Bearer scheme',
bearerFormat: 'JWT'
})
.build();Basic Authentication
const config = new DocumentBuilder()
.addBasicAuth({
name: 'basic',
description: 'Basic HTTP Authentication'
})
.build();API Key
const config = new DocumentBuilder()
.addApiKey({
name: 'api-key',
in: 'header', // or 'query' or 'cookie'
paramName: 'X-API-KEY',
description: 'API Key Authentication'
})
.build();OAuth2
const config = new DocumentBuilder()
.addOAuth2({
name: 'oauth2',
description: 'OAuth2 Authentication',
flows: {
authorizationCode: {
authorizationUrl: 'https://example.com/oauth/authorize',
tokenUrl: 'https://example.com/oauth/token',
scopes: {
'read:users': 'Read user information',
'write:users': 'Modify user information',
}
}
}
})
.build();Applying Security
Global Security
Apply security to all endpoints:
const config = new DocumentBuilder()
.addBearerAuth()
.addSecurity('bearer', []) // Apply globally
.build();Controller-Level Security
Apply security to all routes in a controller:
import { Controller } from '@dwex/core';
import { ApiBearerAuth } from '@dwex/openapi';
@Controller('users')
@ApiBearerAuth()
export class UsersController {
// All routes require Bearer authentication
}Route-Level Security
Apply security to specific routes:
import { Get } from '@dwex/core';
import { ApiBearerAuth } from '@dwex/openapi';
@Controller('users')
export class UsersController {
@Get()
findAll() {
// Public route
return [];
}
@Get('profile')
@ApiBearerAuth()
getProfile() {
// Protected route
return {};
}
}Security Decorators
@ApiBearerAuth
Require Bearer token authentication:
@Controller('users')
@ApiBearerAuth()
export class UsersController {}With scopes:
@Get('admin')
@ApiBearerAuth(['admin', 'write'])
adminOnly() {
return { message: 'Admin area' };
}@ApiBasicAuth
Require Basic authentication:
@Controller('legacy')
@ApiBasicAuth()
export class LegacyController {}@ApiApiKeyAuth
Require API Key authentication:
@Controller('api')
@ApiApiKeyAuth('api-key')
export class ApiController {}@ApiSecurity
Custom security requirements:
import { ApiSecurity } from '@dwex/openapi';
@Controller('admin')
@ApiSecurity('oauth2', ['admin', 'write:users'])
export class AdminController {}Multiple Security Schemes
Apply multiple security schemes:
const config = new DocumentBuilder()
.addBearerAuth({ name: 'jwt' })
.addApiKey({
name: 'api-key',
in: 'header',
paramName: 'X-API-KEY'
})
.build();Use them in controllers:
import { ApiSecurity } from '@dwex/openapi';
@Controller('users')
@ApiSecurity('jwt', [])
@ApiSecurity('api-key', [])
export class UsersController {
// Accepts either JWT or API Key
}Complete Example
// main.ts
import { DwexFactory } from '@dwex/core';
import { DocumentBuilder, OpenApiModule } from '@dwex/openapi';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await DwexFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('My API')
.setVersion('1.0')
// Add Bearer auth for JWT tokens
.addBearerAuth({
name: 'JWT',
description: 'JWT Authorization header',
bearerFormat: 'JWT'
})
// Add API Key for service-to-service
.addApiKey({
name: 'api-key',
in: 'header',
paramName: 'X-API-KEY',
description: 'API Key for service authentication'
})
.build();
const document = OpenApiModule.createDocument(app, config);
OpenApiModule.setup('/docs', app, document);
await app.listen(3000);
}
bootstrap();// users.controller.ts
import { Controller, Get, Post, Body, UseGuards } from '@dwex/core';
import {
ApiTags,
ApiBearerAuth,
ApiApiKeyAuth,
ApiOperation,
ApiOkResponse,
ApiUnauthorizedResponse,
ApiForbiddenResponse,
} from '@dwex/openapi';
import { AuthGuard } from './auth.guard';
import { RolesGuard } from './roles.guard';
@Controller('users')
@ApiTags('users')
export class UsersController {
// Public route - no auth required
@Get('public')
@ApiOperation({ summary: 'Get public user list' })
@ApiOkResponse({ description: 'Public user data' })
getPublicUsers() {
return [];
}
// JWT protected route
@Get('profile')
@UseGuards(AuthGuard)
@ApiBearerAuth()
@ApiOperation({ summary: 'Get current user profile' })
@ApiOkResponse({ description: 'User profile' })
@ApiUnauthorizedResponse({ description: 'Not authenticated' })
getProfile() {
return {};
}
// Admin only route
@Get('admin')
@UseGuards(AuthGuard, RolesGuard)
@ApiBearerAuth()
@ApiOperation({ summary: 'Admin only endpoint' })
@ApiOkResponse({ description: 'Admin data' })
@ApiUnauthorizedResponse({ description: 'Not authenticated' })
@ApiForbiddenResponse({ description: 'Insufficient permissions' })
adminOnly() {
return { message: 'Admin area' };
}
// Service-to-service with API Key
@Post('sync')
@ApiApiKeyAuth('api-key')
@ApiOperation({ summary: 'Sync user data (service-to-service)' })
@ApiOkResponse({ description: 'Sync completed' })
@ApiUnauthorizedResponse({ description: 'Invalid API key' })
syncUsers(@Body() data: any) {
return { status: 'synced' };
}
}Security Responses
Document common security responses:
import {
ApiUnauthorizedResponse,
ApiForbiddenResponse,
} from '@dwex/openapi';
@Get('protected')
@ApiBearerAuth()
@ApiUnauthorizedResponse({
description: 'Missing or invalid authentication token'
})
@ApiForbiddenResponse({
description: 'Insufficient permissions to access this resource'
})
getProtected() {
return {};
}OAuth2 Scopes
Document required OAuth2 scopes:
const config = new DocumentBuilder()
.addOAuth2({
name: 'oauth2',
flows: {
authorizationCode: {
authorizationUrl: 'https://example.com/oauth/authorize',
tokenUrl: 'https://example.com/oauth/token',
scopes: {
'read:users': 'Read user information',
'write:users': 'Modify user information',
'delete:users': 'Delete users',
'admin': 'Admin access',
}
}
}
})
.build();Use in controllers:
import { ApiSecurity } from '@dwex/openapi';
@Controller('users')
export class UsersController {
@Get()
@ApiSecurity('oauth2', ['read:users'])
findAll() {}
@Post()
@ApiSecurity('oauth2', ['write:users'])
create() {}
@Delete(':id')
@ApiSecurity('oauth2', ['delete:users', 'admin'])
remove() {}
}