> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uplift.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook secrets

> Setting Up a Secret Token to Validate Webhooks Requests from Uplift

Integrating a secret token with your [webhook](/guides/platform-configuration/setting-up-webhooks-in-the-uplift-platform) is important to confirm that the requests are indeed coming from Uplift. Creating and adding this secret is easy:

1. Navigate to **Create Webhook** modal.

2. While creating a webhook, provide a secret token along with other webhook details.

3. The secret token should be set as a random string with high entropy:

   1. Ruby: `ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'`

   2. Python: `import os, binascii; print(binascii.hexlify(os.urandom(20)))`

   3. Node: `require('crypto').randomBytes(20).toString('hex');`

4. Click **`Create`** to create the webhook.

5. Ensure that you store the secret token provided while creating of webhook safely and store it in the environment variable of your server for validation of payloads from Uplift.

6. **Never** hardcode the secret token into your app!

## Validating payloads from Uplift

Once you set a secret token, Uplift uses the token to create a hash signature for each payload and sends it via the **`x-uplift-signature-256`** header.

Now the intention is to calculate a hash using your secret token and then compare it to the hash provided by Uplift. You'll successfully validate that the payload was sent by Uplift if you find the hash calculated by you to be the same as the hash sent by Uplift.

Here are some sample **`verify_signature`** functions in different languages:

* **Python:**
  `import os   import hmac   import hashlib`
  `def verify_signature(request_body, signature_from_request_header):`
  `calculated_signature = 'sha256=' + hmac.new(bytes(os.environ['SECRET_TOKEN'], encoding='utf-8'), request_body.encode('utf-8'), hashlib.sha256).hexdigest()`
  `return hmac.compare_digest(calculated_signature, signature_from_request_header)`

* **Node:**
  `const crypto = require('crypto');`
  `const verify_signature = (request_body, signature_from_request_header) => {`
  `return crypto.timingSafeEqual(Buffer.from(signature_from_request_header), Buffer.from('sha256=' + crypto.createHmac('sha256', process.env.SECRET_TOKEN).update(request_body).digest('hex')))`
  `}`

* **Ruby:**
  `def verify_signature(request_body, signature_from_request_header)`
  `calculated_signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], request_body)`
  `return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, signature_from_request_header)`
  `end`

Uplift uses an HMAC hex digest to compute the hash. You could set up a **`verify_signature`** to calculate the hash and verify it with the hash provided by Uplift in the **`x-uplift-signature-256`** header.

Your language and server implementations may differ from the example code provided above. However, there are some important things to point out:

1. No matter which implementation you use, the hash signature starts with `sha256=`, using the key of your secret token and the payload body.

2. Using a plain `==` operator is not advised. A method like [`compare_digest`](https://docs.python.org/3/library/hmac.html#hmac.compare_digest) / [`timingSafeEqual`](https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b) / [`secure_compare`](https://rubydoc.info/github/rack/rack/main/Rack/Utils:secure_compare) performs a "constant time" string comparison, which helps mitigate timing attacks against regular equality operators.

If you need any more assistance setting up Uplift's Secret Token for validating Webhooks requests, please contact your support representative.
