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

# Security

> How do you ensure that the Webhooks you recieve are from Mention Me, and have not been tampered with?

Whenever you create a new Webhook to your external system we **strongly** recommend that you:

1. [Choose a Secret](/api-reference/webhooks/create-destination#step-2-choosing-a-secret)
2. Use the Secret in your external system to validate any incoming data and ensure it's authenticity.

If you follow both of these principles, you're already well on your way to securing your external systems from any bad actors attempting to deliver malicious Webhook data.

## How It Works

Whenever a new Webhook is setup with a Secret, all events which are delivered to the external system will be accompanied by a [HTTP Header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header) with the key `X-MentionMe-Signature`, and a value which will look something like `sha256=<signature here>` (*note that it will always begin with `sha256=` followed by the signature value*).

This signature can be used to:

1. Validate that the Sender (i.e. Mention Me) knows the Secret which was entered [when setting up the Webhook](/api-reference/webhooks/create-destination#step-2-choosing-a-secret).
2. Validate that the body of the Webhook ([examples](/api-reference/webhooks/events#examples-2)) have not been intercepted by a bad actor, and tampered with, *after* they have left the Mention Me platform.

It is the job of the external system to validate this signature and reject any Webhooks which do not match this signature.

## Validation

<Info>
  We **strongly** advise using a **secure comparison function** rather than a standard string comparison (e.g. `==`), and to **fully test the implementation** before deploying to production.
</Info>

The process of validating the signature of a Webhook is simple - you should:

<Steps>
  <Step title="Extract the request body">
    Extract the request body from the [HTTP POST request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/POST).
  </Step>

  <Step title="Retrieve the Secret">
    Retrieve the Secret value in your external system (which **must** be the same value as was provided when setting up the Webhook). We recommend that the Secret be stored securely as an [Environment Variable](https://en.wikipedia.org/wiki/Environment_variable).
  </Step>

  <Step title="Generate the SHA256 hash">
    Generate the SHA256 hash, where the data is the request body, and the key is the Secret.
  </Step>

  <Step title="Compare the hashes">
    Securely compare the resulting SHA256 hash against the one provided in [the request headers](/api-reference/webhooks/security#how-it-works).
  </Step>

  <Step title="Accept or reject">
    If the comparison determines that the hashes are equal, the Webhook's authenticity has been confirmed and can be processed. However, if this is not the case, the Webhook should be rejected.
  </Step>
</Steps>

Many programming languages support secure comparison of SHA265 hashes. Below are some examples which can be used as a starting point.

<CodeGroup>
  ```javascript JavaScript / Node.js theme={null}
  const crypto = require('crypto');

  const validateSignature = (request, secretToken) => {
    const body = request.body;
    const hmac = crypto.createHmac('sha256', secretToken);
    hmac.update(body);

    const signature = `sha256=${hmac.digest('hex')}`;
    const mentionMeSignature = request.headers['X-MentionMe-Signature'];

    return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(mentionMeSignature));
  }
  ```

  ```php PHP theme={null}
  function validateSignature(Request $request, string $secretToken) {
    $signature = "sha256=" . hash_hmac("sha256", $request->getBody(), $secretToken);
    return hash_equals($signature, $request->headers->get("X-MentionMe-Signature"));
  }
  ```

  ```python Python theme={null}
  import hashlib
  import hmac

  def validate_signature(request, secret_token):
      body = request.body.encode('utf-8')
      hmac_obj = hmac.new(secret_token.encode('utf-8'), body, hashlib.sha256)
      signature = 'sha256=' + hmac_obj.hexdigest()
      mentionme_signature = request.headers['X-MentionMe-Signature']

      return hmac.compare_digest(signature.encode('utf-8'), mentionme_signature.encode('utf-8'))
  ```

  ```ruby Ruby theme={null}
  require 'openssl'

  def validate_signature(request, secret_token)
    body = request.body
    hmac = OpenSSL::HMAC.new(secret_token, OpenSSL::Digest.new('sha256'))
    hmac.update(body)

    signature = "sha256=#{hmac.hexdigest}"
    mentionme_signature = request.headers['X-MentionMe-Signature']

    return OpenSSL::SecureCompare.compare(signature, mentionme_signature)
  end
  ```
</CodeGroup>

## Next steps

<Card title="Events" icon="bell" href="/api-reference/webhooks/events">
  See which webhook events are available and their payload formats.
</Card>
