Skip to content

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:

javascript
// ✅ 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:

javascript
// ❌ 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:

EnvironmentFrequencyTrigger
DevelopmentEvery 6 monthsRegular maintenance
StagingEvery 3 monthsAfter major releases
ProductionEvery 3 monthsQuarterly security review
EmergencyImmediatelyAfter security incident

Rotation Process:

  1. Request new API key from FLUID support
  2. Add new key to environment (don't remove old yet)
  3. Deploy changes to all services
  4. Monitor for errors (24-48 hours)
  5. Remove old key from configuration
  6. Request revocation of old key

Environment Separation

Always use separate keys for different environments:

bash
# Development
FLUID_API_KEY=flpk_test_dev_abc123

# Staging
FLUID_API_KEY=flpk_test_staging_xyz789

# Production
FLUID_API_KEY=flpk_live_prod_def456

Critical:

Never use production keys in development or staging environments.

HMAC Authentication

Enable HMAC for all production integrations:

Secret Key Protection

bash
# 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_abc456

Implementation 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 Network

Dynamic IPs (Use VPN or proxy):

203.0.113.50 - Company VPN Gateway

Best 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:

javascript
// ✅ Always use HTTPS
const url = 'https://api.fluid-network.com/api/v1/...';

// ❌ Never use HTTP
const url = 'https://api.fluid-network.com/api/v1/...';  // BLOCKED

Certificate Validation

Always validate SSL certificates:

javascript
// ✅ 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:

javascript
// ✅ 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
javascript
// ✅ 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:

javascript
// ✅ 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
javascript
// ✅ 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 server

Application Security

Input Validation

Validate all inputs before sending to API:

javascript
// ✅ 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:

javascript
// ✅ 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:

javascript
// ✅ 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:

javascript
// ✅ 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:

javascript
// 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

  1. Detect: Monitoring alerts identify potential issue
  2. Assess: Determine severity and scope
  3. Contain: Rotate API keys if compromised
  4. Investigate: Review logs and identify root cause
  5. Remediate: Apply fixes and security patches
  6. Document: Record incident details and lessons learned

Compliance & Auditing

Audit Logging

Log security-relevant events:

javascript
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

bash
# ✅ Never commit secrets
echo ".env" >> .gitignore
echo "config/secrets.yml" >> .gitignore

# ✅ Use git-secrets or similar tools
git secrets --install
git secrets --register-aws

CI/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

Next Steps

Support

Security questions or concerns?

  • Email: security@fluidnetwork.africa
  • Emergency: security@fluidnetwork.africa with [URGENT] prefix
  • Report Vulnerability: security@fluidnetwork.africa with [SECURITY] prefix