Webhooks Security
To ensure webhook security, these requirements must be covered:
webhook source must be verified, so that only webhooks from trusted sources are accepted
webhook message must be verified, so that we are sure the message was not changed by malicious third party
data must be encrypted, so that it can’t be read by malicious third party
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.
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:
Extract the request body as string.
Extract timestamp from the Signature header.
Concatenate timestamp and request body - use dot as separator:
<timestamp>.<requestBody>
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:
Concatenate timestamp from signature header with request body as string
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