HMAC Authentication
HMAC (Hash-based Message Authentication Code) provides an additional layer of security for API requests through cryptographic signatures. When enabled, all requests must include signatures that verify both authenticity and integrity.
Overview
HMAC authentication is an optional security layer that can be enabled on a per-organization basis. It ensures that:
- Requests come from legitimate sources
- Data hasn't been tampered with during transmission
- Requests are fresh (timestamp validation prevents replay attacks)
Key Benefits
| Benefit | Description |
|---|---|
| Message Integrity | Cryptographic proof that request data is unmodified |
| Authentication | Verifies the request comes from a legitimate source |
| Replay Protection | Timestamp validation prevents replay attacks |
| Flexible | Can be enabled/disabled per organization |
How HMAC Works
Authentication Flow
- Client Preparation: Create request with current timestamp
- Signature Generation: Generate HMAC using secret key and request data
- Request Transmission: Send request with HMAC headers
- Server Validation: Server validates timestamp and signature
- Request Processing: If valid, server processes the request
Supported Algorithms
| Algorithm | Description | Output Length | Recommendation |
|---|---|---|---|
sha256 | SHA-256 (Default) | 64 characters | Recommended for most use cases |
sha512 | SHA-512 | 128 characters | Enhanced security for sensitive operations |
Required Headers
When HMAC is enabled, include these headers in every request:
| Header | Description | Format | Example |
|---|---|---|---|
Authorization | Your API key | Bearer {api_key} | Bearer flpk_live_abc123 |
X-FLUID-Timestamp | Unix timestamp | Integer string | 1692364800 |
X-FLUID-Signature | HMAC signature | {algorithm}={signature} | sha256=abc123... |
Signature Generation
Step-by-Step Process
1. Create String-to-Sign
Combine the following elements with newline characters (\n):
HTTP_METHOD + "\n" +
REQUEST_PATH + "\n" +
TIMESTAMP + "\n" +
SHA256_HASH_OF_REQUEST_BODYExample for POST request:
POST
/api/v1/payment-providers/debit-requests/charge
1692364800
d0765f73cd5d1df39be353d538ea7c47a017d66a8bd001dc4707240dbb71e58c2. Generate HMAC Signature
signature = HMAC_{ALGORITHM}(secret_key, string_to_sign)3. Format Header Value
X-FLUID-Signature: sha256={signature}Implementation Examples
The following bash script demonstrates HMAC signature generation. Implement similar logic in your preferred programming language.
#!/bin/bash
# Configuration
API_KEY="your_api_key"
SECRET_KEY="your_secret_key"
ALGORITHM="sha256"
BASE_URL="https://api.fluid-network.com"
# Function to generate HMAC signature
generate_signature() {
local method="$1"
local path="$2"
local timestamp="$3"
local body="$4"
# Create body hash
local body_hash=$(echo -n "$body" | sha256sum | cut -d' ' -f1)
# Create string to sign
local string_to_sign="${method}
${path}
${timestamp}
${body_hash}"
# Generate HMAC signature
echo -n "$string_to_sign" | openssl dgst -$ALGORITHM -hmac "$SECRET_KEY" | cut -d' ' -f2
}
# Create request
METHOD="POST"
PATH="/api/v1/payment-providers/debit-requests/charge"
TIMESTAMP=$(date +%s)
BODY='{
"phone_number": "+233241234567",
"bank_identifier": "ECO",
"amount": 100.00,
"currency": "GHS",
"narration": "Payment for Order #12345",
"partner_reference": "partner_tx_123456"
}'
# Generate signature
SIGNATURE=$(generate_signature "$METHOD" "$PATH" "$TIMESTAMP" "$BODY")
# Make request
curl "${BASE_URL}${PATH}" \
-X POST \
-H "Authorization: Bearer $API_KEY" \
-H "X-FLUID-Timestamp: $TIMESTAMP" \
-H "X-FLUID-Signature: $ALGORITHM=$SIGNATURE" \
-H "Content-Type: application/json" \
-d "$BODY"Implementation Steps:
Generate Timestamp:
- Use current Unix timestamp (seconds since epoch)
- Example:
1692364800
Hash the Request Body:
- Compute SHA-256 hash of the JSON body
- Use empty string
''if no body (GET requests) - Result is hexadecimal string
Create String-to-Sign:
- Concatenate:
METHOD\nPATH\nTIMESTAMP\nBODY_HASH - Use literal newline characters (
\n) - Method must be uppercase (e.g.,
POST,GET)
- Concatenate:
Generate HMAC:
- Use HMAC-SHA256 (or SHA512) with your secret key
- Input is the string-to-sign
- Output is hexadecimal signature
Add Headers:
Authorization: Bearer {api_key}X-FLUID-Timestamp: {timestamp}X-FLUID-Signature: sha256={signature}
Why This Matters:
HMAC signatures prove that:
- The request came from someone with your secret key (authentication)
- The request data hasn't been modified in transit (integrity)
- The request is recent and not a replay of an old request (freshness)
Configuration
Timestamp Window
The timestamp window defines how long a signed request remains valid. Default: 300 seconds (5 minutes).
Recommendations:
- Minimum: 60 seconds (allows for minor clock skew)
- Maximum: 600 seconds (10 minutes)
- Production: 300 seconds (balanced security and usability)
Clock Synchronization:
Ensure your servers are synchronized with NTP to avoid timestamp validation failures.
Error Responses
Missing HMAC Headers
{
"success": false,
"error": {
"code": 1401,
"message": "HMAC signature required",
"category": "authentication",
"severity": "high"
},
"details": "Request missing required HMAC headers",
"meta": {
"timestamp": "2025-01-18T10:30:00Z",
"request_id": "req_abc123"
}
}Invalid Signature
{
"success": false,
"error": {
"code": 1401,
"message": "Invalid HMAC signature",
"category": "authentication",
"severity": "high"
},
"details": "HMAC signature verification failed"
}Expired Timestamp
{
"success": false,
"error": {
"code": 1401,
"message": "Request timestamp expired",
"category": "authentication",
"severity": "high"
},
"details": "Request timestamp is outside the allowed window"
}Invalid Timestamp Format
{
"success": false,
"error": {
"code": 1400,
"message": "Invalid timestamp format",
"category": "validation",
"severity": "medium"
},
"details": "Timestamp must be a valid Unix timestamp"
}Troubleshooting
Common Issues
1. Clock Skew Problems
Symptoms: "Request timestamp expired" errors despite recent requests
Solutions:
- Synchronize server clocks with NTP
- Use
pool.ntp.orgor similar reliable time source - Consider a slightly larger timestamp window (e.g., 600 seconds)
2. Incorrect String-to-Sign
Symptoms: "Invalid HMAC signature" errors
Checklist:
- ✅ HTTP method is uppercase (
POST, notpost) - ✅ Path includes query parameters if present
- ✅ Timestamp matches the header value exactly
- ✅ Body hash is computed correctly
- ✅ Line endings are
\n(not\r\n)
3. Wrong Secret Key
Symptoms: Consistent signature validation failures
Solutions:
- Verify you're using the HMAC secret key, not the API key
- Check for trailing spaces or hidden characters
- Ensure UTF-8 encoding
- Request new secret key from FLUID support if needed
Debugging Tips
Enable detailed logging during development:
console.log('Method:', method);
console.log('Path:', path);
console.log('Timestamp:', timestamp);
console.log('Body Hash:', bodyHash);
console.log('String to Sign:', stringToSign);
console.log('Generated Signature:', signature);Security Warning: Never log secret keys or signatures in production environments.
Best Practices
1. Secret Key Management
- Store secret keys in environment variables or secret vaults
- Never commit secret keys to version control
- Rotate secret keys every 3-6 months
- Use different keys for sandbox and production
2. Implementation Security
- Always use HTTPS for API communications
- Implement reasonable timestamp windows (300-600 seconds)
- Log HMAC validation failures for security monitoring
- Don't expose sensitive information in error messages
3. Testing
Test your HMAC implementation thoroughly:
- Verify signature generation with known inputs
- Test with expired timestamps
- Test with invalid signatures
- Test with missing headers
Enabling HMAC
To enable HMAC authentication for your organization:
- Contact Support: Email support@fluidnetwork.africa
- Request HMAC: Specify your organization and desired algorithm
- Receive Secret Key: FLUID will provide your HMAC secret key
- Update Integration: Implement HMAC signature generation
- Test in Sandbox: Thoroughly test before production
- Go Live: Enable HMAC in production
Next Steps
- IP Whitelisting - Add IP-based access control
- Security Best Practices - Comprehensive security guide
- API Keys - Manage your API credentials
- Error Handling - Handle authentication errors gracefully
Support
Need help with HMAC authentication?
- Email: support@fluidnetwork.africa
- Documentation: https://fluidnetwork.africa/docs