# Signed requests

## Signing requests <a href="#signing-requests" id="signing-requests"></a>

Both webhooks and events can be signed for extra security.

#### Signing webhooks

For webhooks if you'd like the requests to be signed to ensure that they are authentic requests from formsort, you can enable the `sign` security. Read more about creating a webhook [here](/integrations/integration-reference/webhooks.md).

#### Signing events

All events for `variant_revision_published` are signed by default. The signature for verfication  can be found on the "Events" page.

&#x20;

<figure><img src="/files/iNrnDJtVUh0KaJqnCGMr" alt=""><figcaption><p>Click "Show signing key"</p></figcaption></figure>

**Note: The signing key is generated by Formsort, and is different across events and webhooks.**

### How to verify a signature

To generate the signature for verification, use the original HTTP request body (aka JSON payload) and:

1. Hash the request body with SH256, encrypting it with signing key.
   1. You can obtain the key in the Integrations tab when this option is enabled.
2. Base64 encode the result in a URL-safe-way, using `-` and `_` instead of the `+` and `/` characters. This is necessary as Formsort sends the signature in an HTTP header.
3. Remove the trailing `=` signs. Those are often generated by the hashing libraries as padding.

Sample implementations of the signature code follow:

{% tabs %}
{% tab title="Python" %}

```python
import base64
import hashlib
import hmac


def as_bytes(v):
    return v.encode("utf8")


def hmac_sign(signing_key, original_request_body):  # unmodified, a jsonified string
    key = as_bytes(signing_key)
    message = as_bytes(original_request_body)
    return (
        # Note:
        # 1. for url safety, use - and _ characters instead of + and / respectively
        # 2. remove the padding = signs at the end of the signature
        base64.urlsafe_b64encode(
            hmac.new(key, message, hashlib.sha256).digest())
            .rstrip(b"=")
            .decode("utf8")
    )
```

{% endtab %}

{% tab title="Javascript (Express)" %}
To verify a signature in Javascript, the original request buffer can be verified with the signing key like follows:

```javascript
import crypto from 'crypto';

const hmacSign = (signingKey, originalRequestBuffer) => {
    const key = Buffer.from(signingKey, 'utf8');
    return (
        crypto
            .createHmac('sha256', key)
            .update(originalRequestBuffer)
            .digest('base64')
            .replace(/\+/g, '-')
            .replace(/\//g, '_')
            .replace(/=+$/, '')
    );
}
```

\
If you are using `express` as your webserver, and have enabled JSON body parsing with `express.json()` be careful that you are signing the original body buffer and not the parsed JSON. Signing a stringified `req.body` is not reliable due to differences in whitespace between implementations and settings.

The simplest way to do this is to ensure that routes for receiving Formsort webhooks do not apply the JSON middleware.

Using the `hmacSign` function above, assuming a `SIGNING_KEY` environment variable, the following will sign requests from Formsort:

```javascript
import crypto from 'crypto';
import express from 'express';
import bodyParser from 'body-parser';
const PORT = 8080;

const app = express();

app.use((req, res, next) => {
  if (req.header('x-formsort-secure') === 'sign') {
    // Signed formsort requests require verification of the raw body content
    bodyParser.raw({ type: 'application/json' })(req, res, next);
  } else {
    express.json()(req, res, next);
  }
});

const hmacSign = (signingKey, originalRequestBuffer) => {
    const key = Buffer.from(signingKey, 'utf8');
    return (
        crypto
            .createHmac('sha256', key)
            .update(originalRequestBuffer)
            .digest('base64')
            .replace(/\+/g, '-')
            .replace(/\//g, '_')
            .replace(/=+$/, '')
    );
}

app.post('/formsort-webhook', (req, res) => {
  const signature = hmacSign(process.env.SIGNING_KEY, req.body);
  if (signature !== req.header('x-formsort-signature')) {
    return res.status(401).json({ message: 'Formsort signature mismatch' });
  }

  const answers = JSON.parse(req.body);
  return res.json({
    message: 'Well now, it looks like you are all good.',
    answers,
  });
});

app.listen(PORT, () => {
  console.log(`listening on port ${PORT}`);
});
```

{% endtab %}
{% endtabs %}

Note

When signing is enabled, Formsort will send the following additional HTTP headers on webhook requests﻿If signature is enabled, then `X-Formsort-Secure` will have the value of `"sign"` and `X-Formsort-Signature` will have the signature itself.

| Header                 | Value      |
| ---------------------- | ---------- |
| `X-Formsort-Secure`    | sign       |
| `X-Formsort-Signature` | {the hash} |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.formsort.com/integrations/getting-data-out/signed-requests.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
