Webhooks Security

To ensure webhook security, these requirements must be covered:

  1. webhook source must be verified, so that only webhooks from trusted sources are accepted

  2. webhook message must be verified, so that we are sure the message was not changed by malicious third party

  3. data must be encrypted, so that it can’t be read by malicious third party

  4. message timestamp must be used to prevent replay attacks

To ensure all this areas, we use combination of:

  • message signatures, with timestamp included

  • HTTPS protocol - only https url can be configured as webhook URL

Hook secrets

To start with webhook security, client must first generate a hook secret. Secret is used to sign hook request data.

To generate a secret, visit Assigned Clients page in Paygate Back Office application. Then select a client and click Regenerate Hook Secret.

image-20240202-124918.png

Then, copy your secret and store it securely. You can visit page Hook Secrets anytime to view the secret.

Secret regeneration

Client can regenerate hook secret if needed, by clicking on Regenerate Hook Secret action. When new secret is generated, hooks are signed with both old and new secret for 24 hours. You can use this transition period to set up the new secret in your systems.

Signature

Each webhook request contains a Signature header. By verifying the signature, you ensure that Everifin Paygate is caller of your endpoint and that message has not been changed by third party.

Signature header has multiple parts, separated by semicolon:

  • ts: UTC timestamp specifying the time, when signature was created

  • v0: HMAC-SHA256 signature of message

  • v1…: if client has multiple valid hook secrets at the moment of the call, there are multiple versions of signature, for each valid secret. Signature identified as v0 is signed with the oldest valid secret, v1 (and possibly v2…), is signed with a more recent secret.

For example (new lines are used only in example for readability):

ts=2024-01-09T13:08:48.069Z; v0=3cfbc53d4ed906d25489c44dfadc12bc1b4ac806ece1270e236d88735440155d; v1=fcce5bcf8f9bcf76b280520a9c4c0b7ea111bac0ba4ea1536066c5d87e945eb2

Signing algoritm

To verify the message signature, compute the signature of a message and compare it with the signature from request header:

  1. Extract the request body as string.

  2. Extract timestamp from the Signature header.

  3. Concatenate timestamp and request body - use dot as separator: <timestamp>.<requestBody>

  4. Use HMAC-SHA256 algorithm to compute the hexadecimal hash of string created in previous step. Use your hook secret as a HMAC key.

Then, verify that the computed signature is same as signature provided in Signature header (or same as any of signatures, if multiple secrets are valid).

Example

Here we provide example to demonstrate the signing process.

Example hook request body:

{ "eventId": "b2935024-5e46-4cf7-878f-5359526922e5", "eventType": "payment.statusChange", "eventTimestamp": "2024-05-07T15:27:32.197Z", "data": { "paymentId": "0dbe5c2f-3cf3-4177-84fb-5b25c7f6686f", "orderId": "c3ae08d7-5719-4112-bf67-bb9f03e74255", "status": "BOOKED" } }

Example signature header (using secret value abcd):

Signature: ts=2024-05-07T15:27:32.290Z;v0=a7745d8eb55151d67fa8e95197ce34a4276b7ced2f55982630e9275af57ad317

To verify the signature:

  1. Concatenate timestamp from signature header with request body as string

  1. Use HMAC-SHA256 algorithm to compute the hexadecimal hash of string created in previous step.

Replay attacks prevention

Even if the webhook message is signed, an attacker can capture the request and then try to replay the same request.

However, by using the timestamp both in signature header and a signed message payload, we ensure that if an attacker changes a timestamp, the signature is invalidated.

To prevent replay attacks, ignore too old webhook requests (we recommend accepting max. 5 minutes old signatures) and verify the signature correctly.

Security checklist

  • Use HTTPS protocol for your hook endpoints

  • Store your hook secret securely

  • You can also roll hook secrets periodically

  • If your hook secret was compromised, regenerate the secret and use only the new secret to verify the signature

  • Do not accept webhook requests with invalid signature

  • Do not accept webhook requests with too old timestamp in Signature header

  • Optionally, you can also set up IP address whitelist and verify request originator IP address.

    • For production environment, our IP address is 35.189.196.34

    • For staging environment (used only in special cases upon agreement with client), our IP address is 34.79.17.248