@develop-x/nest-internal-auth v1.0.8
@develop-x/nest-internal-auth
Overview
@develop-x/nest-internal-auth
is a NestJS package that provides internal API authentication middleware for microservices communication. It validates API keys to ensure secure service-to-service communication within your infrastructure.
Installation
npm install @develop-x/nest-internal-auth
Features
- API Key Authentication: Secure internal service communication with API keys
- Middleware Integration: Easy integration with NestJS middleware system
- Environment Variable Support: Configurable through environment variables
- Unauthorized Exception Handling: Automatic rejection of invalid requests
- Header Flexibility: Supports multiple header formats for API keys
Usage
Module Import
Import the InternalAuthModule
in your application module:
import { Module } from '@nestjs/common';
import { InternalAuthModule } from '@develop-x/nest-internal-auth';
@Module({
imports: [InternalAuthModule],
// ... other module configuration
})
export class AppModule {}
Environment Configuration
Set the internal API key in your environment variables:
# .env file
INTERNAL_API_KEY=your-secret-api-key-here
Applying Middleware
Global Application
Apply the middleware globally to protect all routes:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { InternalAuthMiddleware } from '@develop-x/nest-internal-auth';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Apply middleware globally
app.use(new InternalAuthMiddleware().use);
await app.listen(3000);
}
bootstrap();
Specific Routes
Apply the middleware to specific routes or controllers:
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { InternalAuthMiddleware } from '@develop-x/nest-internal-auth';
@Module({
// ... module configuration
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(InternalAuthMiddleware)
.forRoutes(
{ path: '/internal/*', method: RequestMethod.ALL },
{ path: '/admin/*', method: RequestMethod.ALL }
);
}
}
Controller Level
Apply the middleware at the controller level:
import { Controller, Get, UseGuards } from '@nestjs/common';
import { InternalAuthMiddleware } from '@develop-x/nest-internal-auth';
@Controller('internal')
export class InternalController {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(InternalAuthMiddleware)
.forRoutes(InternalController);
}
@Get('health')
getHealth() {
return { status: 'ok' };
}
}
API Reference
InternalAuthMiddleware
The main middleware class that validates API keys.
Headers
The middleware accepts API keys in the following headers:
x-api-key
(lowercase)X-API-KEY
(uppercase)
Authentication Flow
- Extract API key from request headers
- Compare with
INTERNAL_API_KEY
environment variable - Allow request if keys match
- Throw
UnauthorizedException
if keys don't match or are missing
Client Usage
Making Authenticated Requests
When calling internal APIs, include the API key in the request headers:
// Using axios
import axios from 'axios';
const response = await axios.get('http://internal-service/api/data', {
headers: {
'x-api-key': process.env.INTERNAL_API_KEY
}
});
// Using fetch
const response = await fetch('http://internal-service/api/data', {
headers: {
'X-API-KEY': process.env.INTERNAL_API_KEY
}
});
// Using NestJS HttpService
import { HttpService } from '@nestjs/axios';
@Injectable()
export class ApiClient {
constructor(private readonly httpService: HttpService) {}
async getData() {
return this.httpService.get('http://internal-service/api/data', {
headers: {
'x-api-key': process.env.INTERNAL_API_KEY
}
}).toPromise();
}
}
Security Considerations
API Key Management
- Environment Variables: Store API keys in environment variables, never in code
- Key Rotation: Regularly rotate API keys for better security
- Unique Keys: Use different API keys for different environments (dev, staging, prod)
- Strong Keys: Generate cryptographically strong API keys
Best Practices
// Good: Using environment variables
const apiKey = process.env.INTERNAL_API_KEY;
// Bad: Hardcoded API key
const apiKey = 'hardcoded-api-key-123';
Key Generation
Generate secure API keys using cryptographic libraries:
# Using openssl
openssl rand -hex 32
# Using Node.js crypto
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Error Handling
Unauthorized Responses
When authentication fails, the middleware throws an UnauthorizedException
:
{
"statusCode": 401,
"message": "Invalid internal API key",
"error": "Unauthorized"
}
Custom Error Handling
You can create custom exception filters to handle authentication errors:
import { ExceptionFilter, Catch, ArgumentsHost, UnauthorizedException } from '@nestjs/common';
import { Response } from 'express';
@Catch(UnauthorizedException)
export class AuthExceptionFilter implements ExceptionFilter {
catch(exception: UnauthorizedException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
response.status(401).json({
error: 'Authentication Failed',
message: 'Invalid or missing internal API key',
timestamp: new Date().toISOString()
});
}
}
Integration Examples
With Service Discovery
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { ConsulService } from '@develop-x/nest-consul';
@Injectable()
export class InternalApiClient {
constructor(
private readonly httpService: HttpService,
private readonly consulService: ConsulService
) {}
async callInternalService(serviceName: string, endpoint: string) {
const serviceUrl = await this.consulService.getServiceUrl(serviceName);
return this.httpService.get(`${serviceUrl}${endpoint}`, {
headers: {
'x-api-key': process.env.INTERNAL_API_KEY
}
}).toPromise();
}
}
With Circuit Breaker
import { Injectable } from '@nestjs/common';
import { HttpClientService } from '@develop-x/nest-service-connector';
@Injectable()
export class ResilientApiClient {
constructor(private readonly httpClient: HttpClientService) {}
async callWithCircuitBreaker(serviceName: string, endpoint: string) {
return this.httpClient
.createRequest(serviceName)
.setPath(endpoint)
.setHeaders({
'x-api-key': process.env.INTERNAL_API_KEY
})
.get();
}
}
Testing
Unit Testing
import { Test, TestingModule } from '@nestjs/testing';
import { UnauthorizedException } from '@nestjs/common';
import { InternalAuthMiddleware } from '@develop-x/nest-internal-auth';
describe('InternalAuthMiddleware', () => {
let middleware: InternalAuthMiddleware;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [InternalAuthMiddleware],
}).compile();
middleware = module.get<InternalAuthMiddleware>(InternalAuthMiddleware);
});
it('should allow request with valid API key', () => {
const req = {
headers: { 'x-api-key': process.env.INTERNAL_API_KEY }
};
const res = {};
const next = jest.fn();
expect(() => middleware.use(req, res, next)).not.toThrow();
expect(next).toHaveBeenCalled();
});
it('should reject request with invalid API key', () => {
const req = {
headers: { 'x-api-key': 'invalid-key' }
};
const res = {};
const next = jest.fn();
expect(() => middleware.use(req, res, next)).toThrow(UnauthorizedException);
});
});
Dependencies
@nestjs/common
: NestJS common utilitiesexpress
: Express.js types for request/response handling
License
ISC
Support
For issues and questions, please refer to the project repository or contact the development team.