> For the complete documentation index, see [llms.txt](/llms.txt)

# Manual webhook signature verification

## Webhook security

For API v3 users, we recommend that you use the [built-in
support](https://documentation.identity.entrust.com/api/latest/#verifying-webhook-signatures) for
webhook verification in our client libraries.

If you're unable to do so (for example, you're using API v2), you can follow
the instructions on this page.

## Extract the signature and event body

Each webhook event will have an `X-SHA2-Signature` header. This contains the
webhook event’s signature in hexadecimal format.

Make sure you use the raw event request body. If you parse it from JSON first,
the fields may be reordered.

## Compute the expected signature

You can get the expected signature of the webhook by computing the HMAC of the
event request body using the SHA256 algorithm, using the webhook’s secret
token as the key.

## Compare the signatures

A webhook event is valid if the signature from the header is equal to the
expected signature you compute for it. Make sure signatures are both in
binary, or both in hexadecimal, before comparing.

You should use a constant time equality function to prevent timing attacks. A
timing attack is where a malicious user measures the small time differences
taken to compare the signatures over many requests, to eventually work out the
expected signature for a webhook event. A constant time equality function
prevents this by always taking the same amount of time when comparing strings
of a particular length.

## Example pseudocode

You may find the following pseudocode useful:

```python
def verify_webhook_event_signature(webhook_event_request)
  signature_header_hexadecimal = webhook_event_request.get_header("x-sha2-signature")

  # Make sure to use the raw event body and not to convert it to an object first.
  raw_event_body = webhook_event_request.body_as_string

  # Compute the HMAC using the SHA256 algorithm and using your webhook's token as the key.
  expected_signature = hmac(algorithm="SHA256", key=webhook_token, data=raw_event_body)

  # Make sure signatures are both in binary, or both in hexadecimal, before comparing.
  signature_header = decode_hexadecimal(signature_header_hexadecimal)

  # Use a constant time equality function to prevent timing attacks.
  if constant_time_equals(signature_header, expected_signature)
    # It is now safe to parse the event body.
    return parse_json(raw_event_body)
  else
    # Handle an invalid webhook event.
    error("Invalid webhook event")
```