Webhook Security
Partner Webhook Integration Guide
Secure Webhook Integration with Coinme
Table of Contents
- Overview
- Security Options Available
- HMAC Signature Authentication
- SSL/TLS Encryption
- API Key Authentication
- Security Feature Combinations
- Webhook Request Format
- Integration Checklist
- Testing Your Integration
- Support and Contact
- Security Best Practices Summary
Appendix: Security Feature Comparison
Overview
Coinme's notification service sends real-time webhook notifications to partner endpoints. We support multiple security options to ensure secure and authenticated delivery of notifications. This guide explains the available security features and how to integrate them.
Security Options Available
Coinme provides three security features that can be enabled individually or in combination:
| # | Feature | Description |
|---|---|---|
| 1 | HMAC Signature Authentication | Verify webhook authenticity |
| 2 | SSL/TLS Encryption | Secure transport layer |
| 3 | API Key Authentication | Simple header-based authentication |
1. HMAC Signature Authentication
What It Is
HMAC (Hash-based Message Authentication Code) signatures allow you to verify that webhooks are authentic and haven't been tampered with. Each webhook includes a cryptographic signature in the HTTP header that you can verify using a shared secret.
How It Works
Coinme Side | Your Side |
|---|---|
|
|
|
|
|
|
|
Configuration
To enable HMAC signatures, provide Coinme with:
- Signature Secret: A shared secret key (we recommend at least 32 characters)
- Signature Header Name (optional): Custom header name (default: X-Coinme-Signature)
Integration Example
Node.js Example
const crypto = require('crypto');
function verifyWebhookSignature(requestBody, signatureHeader, secret) {
// Compute HMAC-SHA256
const hmac = crypto.createHmac('sha256', secret);
hmac.update(requestBody, 'utf8');
// Base64 encode
const computedSignature = hmac.digest('base64');
// Compare signatures
return crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(signatureHeader)
);
}
// Usage
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-coinme-signature'];
const isValid = verifyWebhookSignature(
req.body.toString(),
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook
const payload = JSON.parse(req.body);
// ... handle webhook
});Python Example
import hmac
import hashlib
import base64
def verify_webhook_signature(request_body, signature_header, secret):
# Compute HMAC-SHA256
computed_signature = hmac.new(
secret.encode('utf-8'),
request_body.encode('utf-8'),
hashlib.sha256
).digest()
# Base64 encode
computed_signature_b64 = base64.b64encode(computed_signature).decode('utf-8')
# Compare signatures (use constant-time comparison)
return hmac.compare_digest(computed_signature_b64, signature_header)
# Usage (Flask example)
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Coinme-Signature')
body = request.get_data(as_text=True)
if not verify_webhook_signature(body, signature, os.environ['WEBHOOK_SECRET']):
return 'Invalid signature', 401
# Process webhook
payload = json.loads(body)
# ... handle webhookBest Practices
- Always verify signatures before processing webhooks
- Use constant-time comparison to prevent timing attacks
- Store secrets securely (environment variables, secret management systems)
- Never log signature secrets
- Rotate secrets periodically (coordinate with Coinme support)
Troubleshooting
| Issue | Solution |
|---|---|
| Signature mismatch | Ensure you're using the exact same secret key |
| Encoding errors | Use UTF-8 encoding for payload and secret |
| Header not found | Check header name (default: X-Coinme-Signature) |
| Base64 decode fails | Verify signature header format |
2. SSL/TLS Encryption
What It Is
SSL/TLS encryption ensures that webhook data is encrypted in transit between Coinme and your endpoint. We support both standard HTTPS and mutual TLS (mTLS) with client certificates.
How It Works
Standard HTTPS
- Your endpoint must support HTTPS (TLS 1.2 or higher)
- Valid SSL certificate required
- Certificate must be from a trusted Certificate Authority (CA)
Mutual TLS (mTLS)
- Both parties authenticate with certificates
- You provide client certificate and private key to Coinme
- Coinme uses these to authenticate when connecting to your endpoint
Certificate Requirements
- Format: PEM (preferred) or DER
- Key Size: RSA 2048-bit minimum, or ECDSA equivalent
- Validity: Certificates should be valid and not expired
- Chain: Include full certificate chain if using intermediate CAs
Integration Example - Nginx Configuration (mTLS)
server {
listen 443 ssl;
server_name webhook.yourdomain.com;
# Server certificate
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
# Client certificate verification
ssl_client_certificate /path/to/ca.crt; # Coinme's CA
ssl_verify_client on;
ssl_verify_depth 2;
location /webhook {
proxy_pass http://localhost:3000;
proxy_set_header X-Client-Cert $ssl_client_cert;
}
}3. API Key Authentication
What It Is
API key authentication is a simple method where Coinme includes an API key in a custom HTTP header when sending webhooks. You verify this key matches your expected value.
How It Works
| Coinme Side | Your Side |
|---|---|
| Include your API key in custom HTTP header | Extract API key from configured header |
| Header name is configurable | Compare with stored API key value |
| Reject requests with invalid or missing keys |
Integration Example
// Node.js Example
app.post('/webhook', (req, res) => {
const apiKey = req.headers['x-api-key'];
const expectedKey = process.env.API_KEY;
if (apiKey !== expectedKey) {
return res.status(401).send('Invalid API key');
}
// Process webhook
const payload = req.body;
// ... handle webhook
});# Python Example
@app.route('/webhook', methods=['POST'])
def webhook():
api_key = request.headers.get('X-API-Key')
expected_key = os.environ['API_KEY']
if api_key != expected_key:
return 'Invalid API key', 401
# Process webhook
payload = request.json
# ... handle webhookSecurity Considerations
Note: API key authentication alone provides basic security. For stronger security, combine with:
- HMAC signatures (recommended)
- SSL/TLS encryption (required for production)
4. Security Feature Combinations
You can enable any combination of security features based on your requirements:
Recommended Configurations
Production (High Security)
- HMAC Signature Authentication
- SSL/TLS Encryption (HTTPS)
- API Key Authentication (optional)
Staging/Development
- HMAC Signature Authentication
- SSL/TLS Encryption (HTTPS)
Basic Security
- SSL/TLS Encryption (HTTPS)
- API Key Authentication
5. Webhook Request Format
Standard Webhook Request
POST /webhook HTTP/1.1
Host: your-endpoint.com
Content-Type: application/json
X-Coinme-Signature: <base64-encoded-hmac-signature>
X-API-Key: <your-api-key>
Content-Length: 1234
{
"eventType": "ORDER_CREATED",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
// Event-specific data
}
}Headers Included
| Header | When Included | Description |
|---|---|---|
| Content-Type | Always | application/json |
| X-Coinme-Signature | If HMAC enabled | Base64-encoded HMAC-SHA256 signature |
| X-API-Key | If API key configured | Your configured API key value |
| Custom headers | As configured | Any custom headers you've specified |
6. Integration Checklist
Use this checklist to ensure proper integration:
Pre-Integration
- Determine which security features you need
- Prepare webhook endpoint (HTTPS required)
- Generate HMAC secret (if using signatures)
- Generate API key (if using API key auth)
- Prepare SSL certificates (if using mTLS)
Configuration
- Contact Coinme support to configure security features
- Provide webhook URL to Coinme
- Share HMAC secret securely (if using signatures)
- Share API key securely (if using API key auth)
- Provide SSL certificates (if using mTLS)
Implementation
- Implement HMAC signature verification (if enabled)
- Implement API key validation (if enabled)
- Configure SSL/TLS on your endpoint
- Test webhook reception
- Test signature verification (if enabled)
- Test API key validation (if enabled)
Testing
- Test webhook delivery from Coinme
- Verify signature validation (if enabled)
- Verify API key validation (if enabled)
- Test error handling (invalid signature, invalid key)
- Test SSL/TLS connection (if enabled)
- Monitor webhook logs
Production
- Enable all security features
- Monitor webhook delivery
- Set up alerts for failures
- Document your integration
- Plan for secret rotation
7. Testing Your Integration
Test Webhook Endpoint
Create a test endpoint to verify your integration:
// Test endpoint example
app.post('/webhook-test', express.raw({ type: 'application/json' }), (req, res) => {
console.log('Headers:', req.headers);
console.log('Body:', req.body.toString());
// Verify signature
if (req.headers['x-coinme-signature']) {
const isValid = verifyWebhookSignature(
req.body.toString(),
req.headers['x-coinme-signature'],
process.env.WEBHOOK_SECRET
);
console.log('Signature valid:', isValid);
}
// Verify API key
if (req.headers['x-api-key']) {
const keyValid = req.headers['x-api-key'] === process.env.API_KEY;
console.log('API key valid:', keyValid);
}
res.status(200).send('OK');
});Common Test Scenarios
| Scenario | Expected Result |
|---|---|
| Valid webhook | Should process successfully |
| Invalid signature | Should return 401 |
| Missing signature | Should return 401 (if required) |
| Invalid API key | Should return 401 |
| Missing API key | Should return 401 (if required) |
| Malformed payload | Should handle gracefully |
8. Support and Contact
Getting Help
- Integration Support: Contact your Coinme account manager
- Security Configuration: Reach out to Coinme support team
- Technical Issues: Submit a support ticket
Required Information
When requesting support, please provide:
- Partner ID
- Webhook endpoint URL
- Security features you want to enable
- Any error messages or logs
- Integration environment (dev/staging/prod)
9. Security Best Practices Summary
| Do's | Don'ts |
|---|---|
| Always verify HMAC signatures | Don't skip signature verification |
| Use HTTPS for all webhook endpoints | Don't use HTTP (use HTTPS) |
| Store secrets securely (never in code) | Don't log secrets or API keys |
| Use constant-time comparison for signatures | Don't use weak secrets or keys |
| Monitor webhook delivery and failures | Don't ignore SSL certificate warnings |
| Rotate secrets and keys periodically | Don't hardcode secrets in your code |
| Implement proper error handling | Don't share secrets via insecure channels |
| Log security events (without logging secrets) |
Appendix: Security Feature Comparison
| Feature | Security Level | Complexity | Use Case |
|---|---|---|---|
| API Key | Low-Medium | Low | Simple authentication |
| SSL/TLS | Medium | Medium | Data encryption in transit |
| HMAC Signature | High | Medium | Message authenticity & integrity |
| mTLS | Very High | High | Maximum security with mutual authentication |
Recommended: Use HMAC signatures + SSL/TLS for production environments.
For questions or additional support, please contact your Coinme account manager or support team.
Updated about 1 month ago