Webhook Authentication
Securing your webhook endpoints is critical to ensure that only Beedeez can send notifications to your system. This guide explains the authentication methods available for webhook endpoints.
Why Authentication Matters
Without proper authentication, your webhook endpoint could receive:
- Malicious requests from unauthorized sources
- Spoofed data that appears to come from Beedeez
- Denial of service attacks
Always implement authentication for production webhook endpoints.
Authentication Methods
Beedeez supports five authentication methods for webhook endpoints. Choose the method that best fits your infrastructure and security requirements.
1. None (Not Recommended)
No authentication is applied to webhook requests.
Configuration:
{
"auth": {
"authType": "none"
}
}
When to Use:
- Testing and development only
- Internal networks with other security measures
- Temporary debugging
Security Note: ⚠️ Never use this in production environments.
2. Bearer Token
Sends an Authorization header with a Bearer token.
Configuration:
{
"auth": {
"authType": "bearer_token",
"token": "your-secret-bearer-token"
}
}
Request Header:
Authorization: Bearer your-secret-bearer-token
When to Use:
- Modern REST APIs
- OAuth 2.0 compatible systems
- Token-based authentication systems
Best Practices:
- Use long, randomly generated tokens (minimum 32 characters)
- Rotate tokens periodically
- Store tokens securely (never in source code)
- Use different tokens for different environments
Example Token Generation (Node.js):
const crypto = require('crypto');
const token = crypto.randomBytes(32).toString('hex');
// Example: "a7f3c9e8b2d4f1a6e9c7b5d3f8e2a1c4..."
3. Basic Authentication
Sends credentials using HTTP Basic Authentication.
Configuration:
{
"auth": {
"authType": "basic_auth",
"username": "your-username",
"password": "your-secure-password"
}
}
Request Header:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
(Base64 encoded username:password)
When to Use:
- Legacy systems requiring Basic Auth
- Simple authentication requirements
- Systems with existing Basic Auth infrastructure
Best Practices:
- Use strong, unique passwords
- Combine with HTTPS (required)
- Consider using service accounts with limited permissions
- Rotate credentials regularly
4. API Key
Sends an API key in the X-API-Key header.
Configuration:
{
"auth": {
"authType": "api_key",
"token": "your-api-key"
}
}
Request Header:
X-API-Key: your-api-key
When to Use:
- APIs that expect API keys in headers
- Microservices architectures
- Cloud platforms (AWS API Gateway, Google Cloud Endpoints, etc.)
Best Practices:
- Generate cryptographically secure API keys
- Implement rate limiting on your endpoint
- Monitor API key usage
- Revoke compromised keys immediately
5. Custom Header
Sends authentication credentials in a custom header of your choice.
Configuration:
{
"auth": {
"authType": "custom_header",
"headerName": "X-Custom-Auth",
"headerValue": "your-custom-auth-value"
}
}
Request Header:
X-Custom-Auth: your-custom-auth-value
When to Use:
- Custom authentication schemes
- Legacy systems with non-standard authentication
- Integration with specific platforms requiring custom headers
Best Practices:
- Use descriptive header names (e.g.,
X-Webhook-Secret,X-Integration-Key) - Avoid common header names that might conflict
- Document your custom authentication scheme
- Validate header values strictly on your endpoint
Combining Authentication with Custom Headers
You can combine authentication methods with additional custom headers for enhanced security:
{
"auth": {
"authType": "bearer_token",
"token": "your-bearer-token"
},
"customHeaders": {
"X-Webhook-Source": "beedeez",
"X-Environment": "production",
"X-Correlation-ID": "unique-identifier"
}
}
Resulting Request Headers:
Authorization: Bearer your-bearer-token
X-Webhook-Source: beedeez
X-Environment: production
X-Correlation-ID: unique-identifier
Content-Type: application/json
Validating Webhook Requests
On your webhook endpoint, always validate incoming requests:
1. Verify Authentication
Check that the authentication header matches your expected credentials:
// Example: Bearer Token validation (Node.js/Express)
app.post('/webhooks/beedeez', (req, res) => {
const authHeader = req.headers.authorization;
const expectedToken = process.env.WEBHOOK_BEARER_TOKEN;
if (!authHeader || authHeader !== `Bearer ${expectedToken}`) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Process webhook...
res.status(200).json({ received: true });
});
2. Verify Content Type
Ensure the request has the correct content type:
if (req.headers['content-type'] !== 'application/json') {
return res.status(400).json({ error: 'Invalid content type' });
}
3. Validate Payload Structure
Verify the payload contains expected fields:
const payload = req.body;
if (!payload._id || !payload._userId || !payload._ownerId) {
return res.status(400).json({ error: 'Invalid payload structure' });
}
4. Verify Source (Optional)
If you set custom headers, verify them:
if (req.headers['x-webhook-source'] !== 'beedeez') {
return res.status(403).json({ error: 'Invalid webhook source' });
}
Security Best Practices
Use HTTPS Only
- ✅ Always use HTTPS endpoints (required by Beedeez)
- ✅ Ensure valid SSL/TLS certificates
- ✅ Use TLS 1.2 or higher
Implement Rate Limiting
Protect your endpoint from abuse:
// Example: Simple rate limiting (Node.js)
const rateLimit = require('express-rate-limit');
const webhookLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 100, // Max 100 requests per minute
message: 'Too many webhook requests',
});
app.post('/webhooks/beedeez', webhookLimiter, (req, res) => {
// Handle webhook...
});
Store Credentials Securely
- ✅ Use environment variables or secret management systems
- ✅ Never commit credentials to source control
- ✅ Encrypt credentials at rest
- ✅ Use different credentials per environment
Monitor and Alert
- ✅ Log all webhook requests (including failed authentication)
- ✅ Set up alerts for authentication failures
- ✅ Monitor for unusual patterns
- ✅ Track webhook delivery success rates
Rotate Credentials
- ✅ Rotate authentication credentials periodically (every 90 days)
- ✅ Have a process for emergency credential rotation
- ✅ Update credentials in both Beedeez and your endpoint
IP Whitelisting (Future Enhancement)
While not currently implemented, the webhook configuration schema includes support for IP whitelisting:
{
"security": {
"allowedIps": ["203.0.113.1", "203.0.113.2"]
}
}
This feature will allow you to restrict webhook delivery to specific IP addresses. Contact support if you need this feature.
Troubleshooting Authentication
401 Unauthorized Errors
If your endpoint returns 401 errors:
- Verify the authentication credentials in Beedeez match your endpoint
- Check that the authentication type is configured correctly
- Ensure your endpoint is properly validating the authentication header
- Check for typos in tokens or passwords
403 Forbidden Errors
If your endpoint returns 403 errors:
- Check IP restrictions or firewall rules
- Verify custom header validation logic
- Ensure the request source is allowed
Authentication Not Working
- Test with curl: Send a test request to your endpoint with the same headers Beedeez uses
- Check Logs: Review both Beedeez logs and your endpoint logs
- Verify HTTPS: Ensure your endpoint uses valid HTTPS
- Test Credentials: Verify credentials work in isolation
Example curl test:
curl -X POST https://your-endpoint.com/webhooks/beedeez \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"test": "payload"}'
Example Implementations
Node.js/Express with Bearer Token
const express = require('express');
const app = express();
app.use(express.json());
const WEBHOOK_TOKEN = process.env.BEEDEEZ_WEBHOOK_TOKEN;
app.post('/webhooks/beedeez', (req, res) => {
// Validate authentication
const authHeader = req.headers.authorization;
if (!authHeader || authHeader !== `Bearer ${WEBHOOK_TOKEN}`) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Process webhook
const payload = req.body;
console.log('Received webhook:', payload);
// Respond quickly
res.status(200).json({ received: true });
// Process asynchronously
processWebhookAsync(payload);
});
app.listen(3000);
Python/Flask with API Key
from flask import Flask, request, jsonify
import os
app = Flask(__name__)
WEBHOOK_API_KEY = os.environ.get('BEEDEEZ_WEBHOOK_API_KEY')
@app.route('/webhooks/beedeez', methods=['POST'])
def handle_webhook():
# Validate authentication
api_key = request.headers.get('X-API-Key')
if api_key != WEBHOOK_API_KEY:
return jsonify({'error': 'Unauthorized'}), 401
# Process webhook
payload = request.get_json()
print(f'Received webhook: {payload}')
# Respond quickly
return jsonify({'received': True}), 200
if __name__ == '__main__':
app.run(port=3000)
Next Steps
- Review Configuration Guide to set up authentication
- See Payload Examples for webhook data structures
- Read Event Types to understand available events