Introduction
In today’s interconnected systems, security is crucial for API communication. HMAC (Hash-based Message Authentication Code) is a powerful method to ensure both integrity and authenticity in API calls.
In this article, we’ll cover:
- How HMAC works for API-to-API calls.
- Step-by-step HMAC setup using NestJS and AWS (with UseGuards).
- Postman testing of HMAC-protected endpoints using a custom script.
1. How HMAC Works for API-to-API Calls
What is HMAC?
HMAC combines a secret key and message to generate a unique hash. This ensures:
- Integrity: The message hasn’t been tampered with.
- Authenticity: The request comes from a trusted sender.
Visual Diagram:
How HMAC works
HMAC Flow
- Client: Generates the HMAC hash using a secret key and the request payload.
- Server: Computes the hash on its end using the same secret key.
- Validation: If both hashes match, the request is valid.
2. HMAC Setup Using NestJS and AWS
Step 1: Install Dependencies
Install necessary libraries:
npm install crypto aws-sdk @nestjs/config
Step 2: Store the Secret Key in AWS Secrets Manager
- Go to AWS Console → Secrets Manager → Create a Secret.
- Add your secret key securely.
- Retrieve this key in your NestJS application.
Visual Step-by-Step:
Step 3: Create the HMAC Service
hmac.service.ts
import { Injectable } from '@nestjs/common';
import * as crypto from 'crypto';
import { SecretsManager } from 'aws-sdk';
@Injectable()
export class HmacService {
private secretKey: string;
constructor() {
this.loadSecret();
}
async loadSecret() {
const secretsManager = new SecretsManager({ region: 'us-east-1' });
const secret = await secretsManager
.getSecretValue({ SecretId: 'your-secret-key' })
.promise();
this.secretKey = secret.SecretString || '';
}
generateHmac(payload: string): string {
return crypto
.createHmac('sha256', this.secretKey)
.update(payload)
.digest('hex');
}
validateHmac(payload: string, clientHash: string): boolean {
const serverHash = this.generateHmac(payload);
return serverHash === clientHash;
}
}
Step 4: Use Guards for HMAC Validation
Instead of middleware, create a guard to validate HMAC hashes.
hmac.guard.ts
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { HmacService } from './hmac.service';
@Injectable()
export class HmacGuard implements CanActivate {
constructor(private readonly hmacService: HmacService) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const payload = JSON.stringify(request.body);
const clientHmac = request.headers['x-hmac-signature'] as string;
if (!clientHmac || !this.hmacService.validateHmac(payload, clientHmac)) {
throw new UnauthorizedException('Invalid HMAC signature');
}
return true; // Allow request if HMAC is valid
}
}
Step 5: Apply UseGuards to Routes
app.controller.ts
import { Controller, Post, Body, UseGuards } from '@nestjs/common';
import { HmacGuard } from './hmac.guard';
@Controller('secure-endpoint')
export class AppController {
@Post()
@UseGuards(HmacGuard)
handleSecureEndpoint(@Body() data: any) {
return { message: 'Request successfully validated!', data };
}
}
Visual Representation :-
3. Testing HMAC-Secured Endpoint Using Postman
Step 1: Add Pre-request Script
Generate the HMAC hash dynamically in Postman:
Pre-request Script:
const crypto = require('crypto');
// Payload
const payload = JSON.stringify({
data: 'Sample request payload',
});
// Secret Key (replace with your key)
const secretKey = 'your-shared-secret-key';
// Generate HMAC Hash
const hash = crypto
.createHmac('sha256', secretKey)
.update(payload)
.digest('hex');
// Add HMAC hash to headers
pm.request.headers.add({
key: 'x-hmac-signature',
value: hash,
});
console.log('Generated HMAC:', hash);
Step 2: Configure Postman Request
- Method: POST
- Headers: Automatically set by the script.
- Body: Add payload in JSON format.
Example Payload:
{
"data": "Sample request payload"
}
Step 3: Test and Verify
- Hit Send.
- If the HMAC is valid, you’ll receive a 200 OK response.
Conclusion
By implementing HMAC using NestJS and testing with Postman, you can ensure:
- Integrity and authenticity in API-to-API communication.
- A clean, modular approach using UseGuards for route protection.
- Secure key management with AWS Secrets Manager.
Key Takeaways
- Use HMAC Guards for scalable and modular validation.
- Securely manage shared secrets using AWS Secrets Manager.
- Test HMAC validation easily with Postman scripts.
Let me know how you implement HMAC in your systems! 🚀
Connect with me for more API security insights.
Top comments (1)
Follow for more content like this 🚀