This page is for admins who make Buttons.

The request of a Workflow button has no signature. Any person who knows the URL of your endpoint can send a request
to it. In this guide, you add a secret header to the Button. The endpoint then rejects each request without the
header.

Start with the endpoint from [Receive a Workflow button press](/docs/using-oneclick-with/nodejs/receive-a-workflow-button-press).

## Make a secret

1. Make a long random value, for example with this command:

   ```sh
   node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"
   ```

2. Keep the value in an environment variable on your server, for example `ONECLICK_SECRET`. Do not put it in the
   code.

## Add the header to the Button

1. Open the Button in the Button editor.
2. Turn on the switch at the right of **Headers** in the menu.
3. Click **Headers**.
4. Type `x-api-token` in **Key**.
5. Type the secret in **Value**.
6. Turn on **Confidential**. Other admins then cannot see the secret.
7. Click **Save**.

With a confidential header of another admin, an admin cannot change the **Button URL** or duplicate the Button. See
[Confidential headers](/docs/buttons/workflow-button/sections/headers#confidential-headers).

For the rules of the key and the value, see [Headers](/docs/buttons/workflow-button/sections/headers).

## Check the header on the endpoint

Check the header before the endpoint does other work:

```js
import { timingSafeEqual } from 'node:crypto';

function hasSecret(req) {
	const expected = Buffer.from(process.env.ONECLICK_SECRET ?? '');
	const actual = Buffer.from(req.header('x-api-token') ?? '');
	return expected.length > 0 && actual.length === expected.length && timingSafeEqual(actual, expected);
}

app.post('/oneclick', (req, res) => {
	if (!hasSecret(req)) {
		return res.status(401).end();
	}
	res.json({ message: 'The data is received', message_type: 'success' });
});
```

`timingSafeEqual` compares the values in a constant time. Thus the time of the answer does not tell a part of the
secret.

## Change the secret

1. Make a new secret.
2. Set the new secret in the environment variable.
3. Restart the server.
4. Type the new secret in **Value** in the **Headers** section of the Button.
5. Click **Save**.

Between step 3 and step 5, the endpoint rejects the presses of the Button.
