Security Best Practices
This guide provides comprehensive security recommendations for integrating with the FLUID Network API. Following these practices ensures the safety of your integration and protects sensitive financial data.
Security Architecture
FLUID Network implements a multi-layered security approach:
Authentication Security
API Key Management
Secure Storage
DO:
// ✅ Use environment variables
const apiKey = process.env.FLUID_API_KEY;
// ✅ Use secret management services
const secretManager = new AWS.SecretsManager();
const apiKey = await secretManager.getSecretValue('fluid-api-key');DON'T:
// ❌ Never hardcode credentials
const apiKey = 'flpk_live_abc123xyz456';
// ❌ Never commit to version control
git add .env
// ❌ Never log API keys
console.log('API Key:', apiKey);Key Rotation
Rotate API keys regularly:
| Environment | Frequency | Trigger |
|---|---|---|
| Development | Every 6 months | Regular maintenance |
| Staging | Every 3 months | After major releases |
| Production | Every 3 months | Quarterly security review |
| Emergency | Immediately | After security incident |
Rotation Process:
- Request new API key from FLUID support
- Add new key to environment (don't remove old yet)
- Deploy changes to all services
- Monitor for errors (24-48 hours)
- Remove old key from configuration
- Request revocation of old key
Environment Separation
Always use separate keys for different environments:
# Development
FLUID_API_KEY=flpk_test_dev_abc123
# Staging
FLUID_API_KEY=flpk_test_staging_xyz789
# Production
FLUID_API_KEY=flpk_live_prod_def456Critical:
Never use production keys in development or staging environments.
HMAC Authentication
Enable HMAC for all production integrations:
Secret Key Protection
# Store separately from API keys
FLUID_API_KEY=flpk_live_abc123
FLUID_SECRET_KEY=secret_xyz789 # Used for HMAC only
# Use different secrets per environment
FLUID_PROD_SECRET=secret_prod_xyz789
FLUID_STAGING_SECRET=secret_staging_abc456Implementation Checklist
- ✅ Generate signatures using SHA-256 or SHA-512
- ✅ Include timestamp in every request
- ✅ Validate timestamp is within 300-600 seconds
- ✅ Use secure random number generator for timestamps
- ✅ Never log secret keys or generated signatures
- ✅ Implement signature verification on webhooks
See HMAC Authentication Guide for implementation details.
IP Whitelisting
Restrict API access to known IP addresses:
Configuration Strategy
Static IPs (Recommended for production):
203.0.113.10 - Production Server 1
203.0.113.20 - Production Server 2
198.51.100.0/24 - Office NetworkDynamic IPs (Use VPN or proxy):
203.0.113.50 - Company VPN GatewayBest Practices
- Start with strict mode in production
- Use CIDR ranges for office networks
- Set expiration dates for temporary access
- Monitor blocked IPs regularly
- Update before IP changes to avoid downtime
See IP Whitelisting Guide for configuration details.
Transport Security
TLS/HTTPS
All API communication must use TLS 1.3 or TLS 1.2:
// ✅ Always use HTTPS
const url = 'https://api.fluid-network.com/api/v1/...';
// ❌ Never use HTTP
const url = 'https://api.fluid-network.com/api/v1/...'; // BLOCKEDCertificate Validation
Always validate SSL certificates:
// ✅ Default (validates certificates)
const response = await fetch(url, { headers });
// ❌ Never disable validation
const https = require('https');
const agent = new https.Agent({
rejectUnauthorized: false // DANGEROUS!
});Implementation Note:
Most HTTP libraries validate SSL certificates by default. Never disable certificate validation in production, as this makes your application vulnerable to man-in-the-middle attacks.
Data Security
Sensitive Data Handling
Personal Information
Minimize storage of sensitive data:
// ✅ Store only necessary data
const transaction = {
reference: 'tx_123',
amount: 100.00,
status: 'completed',
// Phone number stored securely elsewhere
};
// ❌ Don't store full customer data
const transaction = {
customer_phone: '+233241234567',
customer_name: 'John Doe',
customer_address: '123 Main St', // Unnecessary
// ...
};Logging Practices
DO log:
- Request IDs
- Timestamps
- Status codes
- Error categories
- Transaction references
DON'T log:
- API keys or secret keys
- HMAC signatures
- Full phone numbers (mask:
+233****4567) - Full account numbers
- Customer personal information
// ✅ Safe logging
logger.info('Transaction created', {
reference: 'tx_123',
status: 'pending',
amount: 100.00,
masked_phone: '+233****4567'
});
// ❌ Unsafe logging
logger.info('Transaction created', {
api_key: 'flpk_live_abc123', // NEVER LOG
phone: '+233241234567', // Use masked version
signature: 'sha256=abc123...' // NEVER LOG
});Data Encryption
At Rest
Encrypt sensitive data in your database:
// ✅ Encrypt before storing
const encryptedPhone = encrypt(phoneNumber, ENCRYPTION_KEY);
await db.transactions.insert({
reference: 'tx_123',
encrypted_phone: encryptedPhone
});
// Decrypt when needed
const phoneNumber = decrypt(record.encrypted_phone, ENCRYPTION_KEY);In Transit
All data is encrypted in transit via TLS. Additionally:
- Use HMAC signatures for integrity verification
- Validate webhook signatures before processing
- Never transmit sensitive data in URL parameters
// ✅ Sensitive data in request body
fetch(url, {
method: 'POST',
body: JSON.stringify({ phone_number: '+233241234567' })
});
// ❌ Sensitive data in URL
fetch(`${url}?phone_number=+233241234567`); // Logged in web serverApplication Security
Input Validation
Validate all inputs before sending to API:
// ✅ Validate phone numbers
function validatePhone(phone) {
const phoneRegex = /^\+[1-9]\d{1,14}$/;
if (!phoneRegex.test(phone)) {
throw new Error('Invalid phone number format');
}
return phone;
}
// ✅ Validate amounts
function validateAmount(amount) {
const amt = parseFloat(amount);
if (isNaN(amt) || amt <= 0 || amt > 1000000) {
throw new Error('Invalid amount');
}
return amt;
}
// ✅ Sanitize user inputs
const narration = sanitize(userInput, { maxLength: 100 });Error Handling
Don't expose sensitive information in error messages:
// ✅ Generic error messages to users
try {
await fluidAPI.createCharge(data);
} catch (error) {
// Log detailed error internally
logger.error('Charge failed', { error, data: sanitize(data) });
// Return generic message to user
return {
success: false,
message: 'Payment processing failed. Please try again.'
};
}
// ❌ Don't expose internal details
catch (error) {
return {
success: false,
message: error.message, // May contain sensitive info
stack: error.stack // NEVER expose stack traces
};
}Rate Limiting
Implement client-side rate limiting to avoid hitting API limits:
// ✅ Implement backoff strategy
class RateLimiter {
constructor(maxRequests, perSeconds) {
this.maxRequests = maxRequests;
this.perSeconds = perSeconds;
this.requests = [];
}
async throttle() {
const now = Date.now();
this.requests = this.requests.filter(t => now - t < this.perSeconds * 1000);
if (this.requests.length >= this.maxRequests) {
const oldestRequest = this.requests[0];
const waitTime = (oldestRequest + this.perSeconds * 1000) - now;
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.requests.push(now);
}
}
const limiter = new RateLimiter(100, 60); // 100 requests per minute
async function makeAPICall() {
await limiter.throttle();
return await fetch(url, options);
}Webhook Security
Signature Verification
Always verify webhook signatures:
// ✅ Verify signature before processing
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(payload).digest('hex');
const expected = `sha256=${digest}`;
// Use timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
app.post('/webhooks/fluid', (req, res) => {
const signature = req.headers['x-fluid-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook
processWebhook(req.body);
res.status(200).json({ received: true });
});Endpoint Security
Secure your webhook endpoint:
- Use HTTPS for webhook URLs
- Verify signatures before processing
- Implement idempotency to handle duplicate deliveries
- Return 200 quickly, process asynchronously
- Rate limit webhook endpoint
See Webhook Signature Verification for details.
Infrastructure Security
Network Security
- Use firewalls to restrict inbound/outbound traffic
- Implement VPN for remote access
- Segment networks (separate production from dev/staging)
- Monitor network traffic for anomalies
Server Hardening
- Keep systems updated with security patches
- Disable unused services and ports
- Use strong passwords and SSH keys
- Implement fail2ban or similar intrusion prevention
- Enable audit logging for all systems
Database Security
- Encrypt data at rest using AES-256
- Use strong passwords for database users
- Limit database access to application servers only
- Regular backups with encryption
- Audit database access logs
Monitoring & Incident Response
Security Monitoring
Monitor for suspicious activity:
// Track failed authentication attempts
if (response.status === 401) {
logger.warn('Authentication failed', {
ip: req.ip,
endpoint: req.path,
timestamp: new Date()
});
// Alert if threshold exceeded
if (failedAttempts > 10) {
alertSecurityTeam('Multiple failed auth attempts', { ip: req.ip });
}
}Alerts to Configure
- Multiple failed authentication attempts
- Requests from unexpected IPs
- Unusual transaction patterns
- Rate limit violations
- Webhook signature failures
- Unexpected error rates
Incident Response Plan
- Detect: Monitoring alerts identify potential issue
- Assess: Determine severity and scope
- Contain: Rotate API keys if compromised
- Investigate: Review logs and identify root cause
- Remediate: Apply fixes and security patches
- Document: Record incident details and lessons learned
Compliance & Auditing
Audit Logging
Log security-relevant events:
auditLog.record({
event: 'api_key_rotation',
actor: 'admin@company.com',
timestamp: new Date(),
details: {
old_key_id: 'key_123',
new_key_id: 'key_456'
}
});Regular Security Reviews
- Monthly: Review access logs for anomalies
- Quarterly: Rotate API keys and review whitelist
- Annually: Full security audit and penetration testing
Data Retention
Follow data retention policies:
- Transaction logs: 7 years (regulatory requirement)
- API logs: 90 days
- Security logs: 1 year
- Customer data: Only as long as necessary
Development Practices
Secure Coding
- Code review all security-related changes
- Static analysis to identify vulnerabilities
- Dependency scanning for known vulnerabilities
- Penetration testing before production deployment
Version Control
# ✅ Never commit secrets
echo ".env" >> .gitignore
echo "config/secrets.yml" >> .gitignore
# ✅ Use git-secrets or similar tools
git secrets --install
git secrets --register-awsCI/CD Security
- Scan dependencies for vulnerabilities
- Run security tests in CI pipeline
- Use secret scanning tools (git-secrets, truffleHog)
- Implement approval gates for production deployments
Quick Security Checklist
Before going to production, verify:
- ✅ API keys stored in environment variables or secret manager
- ✅ Separate keys for development, staging, and production
- ✅ HMAC authentication enabled for production
- ✅ IP whitelisting configured and tested
- ✅ All API calls use HTTPS
- ✅ SSL certificate validation enabled
- ✅ Sensitive data encrypted at rest
- ✅ Logging doesn't include credentials or PII
- ✅ Webhook signature verification implemented
- ✅ Client-side rate limiting implemented
- ✅ Error messages don't expose sensitive details
- ✅ Security monitoring and alerting configured
- ✅ Incident response plan documented
- ✅ Regular security reviews scheduled
Security Resources
FLUID Network Security
- Security Email: security@fluidnetwork.africa
- Report Vulnerability: Use security email with [SECURITY] prefix
Industry Standards
- OWASP API Security: https://owasp.org/www-project-api-security/
- PCI DSS: Payment Card Industry Data Security Standard
- ISO 27001: Information Security Management
Next Steps
- API Keys - Manage your credentials
- HMAC Authentication - Implement signature-based security
- IP Whitelisting - Configure IP-based access control
- Error Handling - Handle errors securely
Support
Security questions or concerns?
- Email: security@fluidnetwork.africa
- Emergency: security@fluidnetwork.africa with [URGENT] prefix
- Report Vulnerability: security@fluidnetwork.africa with [SECURITY] prefix