API Documentation forms an integral part of any application that depends on API and is to be shared. Public exposure of your API documentation can lead to security issues, especially when sensitive, protected or internal API endpoints are exposed. Securing Swagger with authentication is, therefore, very important in preventing such risk issues.
1. Express Using Middleware for Protection
If you're using Express with Node.JS, you may use a middleware function to protect Swagger.
Step 1: Install Basic Auth Middleware. npm install express-basic-auth
Step 2: Apply Middleware to Swagger Routes
const express = require('express');
const basicAuth = require('express-basic-auth');
const swaggerDoc = require('./swagger.json');
const swagger = require('swagger-ui-express');
const app = express();
app.use(
'/api-docs',
basicAuth({
users: { admin: 'securePassword' },
challenge: true,
}),
swagger.serve,
swagger.setup(swaggerDoc)
);
app.listen(3030, () => {
console.log('API running on http://localhost:3030');
});
2. Using Guards (for NestJS) To secure the Swagger route in a NestJS application, you can utilize Guards.
Step 1: Create a Swagger Guard.
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class SwaggerGuard implements CanActivate {
constructor(private readonly configService: ConfigService) { }
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const authHeader = request.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
throw new UnauthorizedException(Invalid authorization header');
}
const base64Credentials = authHeader.split(' ')[1];
const decodedCredentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [username, password] = decodedCredentials.split(':');
//get the username and password from the config file
const usr = this.configService.get("swagger.username");
const pswd = this.configService.get("swagger.password");
if (username === usr && password === pswd) {
return true;
}
throw new UnauthorizedException('Invalid credentials!');
}
}
Step 2: Apply Guard to the Swagger Route
import { SwaggerModule, DocumentBuilder} from '@nestjs/swagger';
import { SwaggerGuard } from './swagger.guard';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const options = new DocumentBuilder()
.setTitle('API Documentation')
.setDescription(OneClick API Documentation')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, SwaggerConfig);
app.use('/api', (req, res, next) => {
const guard = new SwaggerGuard(configService);
try {
guard.canActivate({ switchToHttp: () => ({ getRequest: () => req }) } as any);
next();
} catch (err: unknown) {
const status = (err as any)?.getStatus?.() || 401;
const message = (err as any)?.message || 'Unauthorized access';
res.setHeader('WWW-Authenticate', 'Basic realm="Swagger"');
res.status(status).send(message);
}
});
SwaggerModule.setup('api', app, document);
});
await app.listen(3030);
}
bootstrap();
Adding a password to your Swagger documentation is the simplest and most effective way of making your application secure. By implementing Basic Authentication with express-basic-auth, you prevent unauthorized access to critical API details and ensure compliance with best security practices. Though its tiny size, this step may significantly decrease the possibility of your APIs being vulnerable to attackers.
Ready to transform your business with our technology solutions? Contact Us today to Leverage Our NodeJS Expertise.
0