Skip to main content

Security

To protect your data and ensure secure webhook delivery, the platform provides multiple layers of security. Following these measures and best practices helps prevent unauthorized access, payload tampering, and replay attacks.

1. Originating IP Address Verification

The platform delivers notifications through a set of predefined static IP addresses. Customers are encouraged to whitelist these IPs to ensure only requests from trusted sources are accepted:

  • Static IPs:
    • 34.138.140.223
    • 34.138.161.100
    • 35.231.250.193
    • 35.196.71.29
    • 34.138.56.192

Note: Although these IPs are specific to our webhook provider, they may still be shared with other customers of the provider. While whitelisting is a helpful security layer, it should not be the only method you rely on.

2. Payload HMAC Signature Verification

To verify that notifications genuinely originate from the platform, each payload is signed using a SHA-256 HMAC signature. This signature is included in the X-Synaps-Signature header and can be verified using your unique signing secret, shared per customer.

Steps to Verify the Signature

  1. Retrieve the Signature: Obtain the value of the X-Synaps-Signature header from the incoming request.
  2. Recreate the Signature: Use the same signing secret and SHA-256 HMAC algorithm to hash the payload data.
  3. Compare Signatures: Ensure that the recreated signature matches the signature in the header. A match confirms the authenticity of the payload.

Here are some code snippets to help you verify the signature in different programming languages:

type Server struct {
// Shared secret used to sign the payload
Secret string
}

// Retrieve the signature from the request and decode it
func retrieveSignature(h http.Header) ([]byte, error) {
base64Signature := h.Get("X-Synaps-Signature")
signature, err := base64.StdEncoding.DecodeString(base64Signature)
if err != nil {
return nil, fmt.Errorf("failed to decode signature: %w", err)
}

return signature, nil
}

func (s *Server) verify(b []byte, h http.Header) error {
signature, err := retrieveSignature(h)
if err != nil {
return err
}

// Compute the HMAC signature from the request body with the shared secret
hasher := hmac.New(sha256.New, []byte(s.Secret))
hasher.Write(b)
computed := hasher.Sum(nil)

// Compare the computed signature with the received signature
if !hmac.Equal(signature, computed) {
return errors.New("signature mismatch")
}

return nil
}

3. Preventing Replay Attacks

To guard against replay attacks, two safeguards are provided:

  • Notification Expiration: Each webhook payload includes a created_at field. Customers should implement a threshold (e.g., 5-10 minutes) to reject any notifications received after this expiration window.

Tip: Ensure this threshold is compatible with the maximum retry timeout, so retries don’t unintentionally result in expired notifications.

  • Idempotency Key: Every webhook payload includes a unique idempotency_key. You can store this key temporarily (e.g., in a Redis cache) to check if a notification has been processed previously, preventing duplicate processing.

Example: Store idempotency keys for 24 hours and discard any events with duplicate keys within that timeframe.

Combining Both Methods An effective approach to preventing replay attacks is to use a mix of both expiration and idempotency key checks. For example, store each idempotency_key with a 24-hour expiration in a temporary store like Redis, and discard any incoming notifications older than your chosen threshold.


Best Practices

To further enhance security and reliability, follow these best practices when implementing webhooks:

Whitelist IPs and Verify Signatures

  • Whitelist IP Addresses: Accept incoming webhook requests only from the designated IPs to reduce the chance of unauthorized access.
  • Always Verify Signatures: Signature verification ensures that payloads are authentic and untampered. Implement this verification for all incoming notifications.

Implement Flexible Payload Handling

  • Handle Unexpected Fields: To accommodate future payload changes, configure your webhook handler to ignore unrecognized fields. This prevents errors if new fields are added to the payload.
  • Reject Incomplete Payloads: Validate that the payload contains all expected fields to avoid incomplete or invalid data.

Error Handling and Retry Management

  • Log Errors and Monitor Retries: Set up logging to track failed webhook deliveries and monitor retry attempts. This will help you troubleshoot delivery issues more effectively.
  • Configure Proper HTTP Response Codes: Respond with appropriate status codes (2xx for success, 5xx for server errors) to let the platform know when to retry or stop delivery attempts.

Keep Payload Processing Efficient

  • Optimize Endpoint Performance: Ensure your webhook handler can process events quickly to prevent timeouts.
  • Avoid Blocking Operations: Offload heavy processing tasks to background jobs or asynchronous functions, so your webhook endpoint responds promptly.

Secure Your Endpoint

  • Use HTTPS: Ensure that your webhook endpoint uses HTTPS to encrypt data in transit, protecting it from interception.

By following these security measures and best practices, you can ensure that your webhook implementation is secure, reliable, and ready to handle real-time notifications from the platform.