Skip to main content
Version: Next

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.

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:

  1. Verify the authentication credentials in Beedeez match your endpoint
  2. Check that the authentication type is configured correctly
  3. Ensure your endpoint is properly validating the authentication header
  4. Check for typos in tokens or passwords

403 Forbidden Errors

If your endpoint returns 403 errors:

  1. Check IP restrictions or firewall rules
  2. Verify custom header validation logic
  3. Ensure the request source is allowed

Authentication Not Working

  1. Test with curl: Send a test request to your endpoint with the same headers Beedeez uses
  2. Check Logs: Review both Beedeez logs and your endpoint logs
  3. Verify HTTPS: Ensure your endpoint uses valid HTTPS
  4. 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