> Documentation index: [Saleor](/llms.txt) · [This section](/developer/llms.txt)
> Source: https://docs.saleor.io/developer/extending/webhooks/payload-signature

# Payload Signature

Saleor calculates a payload signature and puts the result into `Saleor-Signature` header:

-   DEPRECATED if `secretKey` was set for a webhook - the HMAC SHA-256 header based on it and the payload
-   if `secretKey` wasn't set for a webhook - the JWS signature using RS256 with payload detached, to verify the signature you can use a public key, which can be fetched from `http(s)://<your-backend-domain>/.well-known/jwks.json`

<a id="validating-signature"></a>

## Validating signature

To validate signatures in Saleor Apps, use [`withWebhookSignatureVerified`](https://github.com/saleor/saleor-app-sdk/blob/main/src/middleware.ts#L62) middleware provided by [`@saleor/app-sdk`](https://github.com/saleor/saleor-app-sdk)

```js
import type { Handler } from "retes";
import { Response } from "retes/response";
import { toNextHandler } from "retes/adapter";
import {
  withSaleorEventMatch,
  withWebhookSignatureVerified,
} from "@saleor/app-sdk/middleware";

const handler: Handler = async (request) => {
  // ...

  return Response.OK({ success: true });
};

export default toNextHandler([
  withSaleorDomainMatch,
  withWebhookSignatureVerified(),
  handler,
]);
```

You can also manually validate the JWS signature in JavaScript with the [`jose` package](https://github.com/panva/jose). Remember that you need to supply it with a raw body string, not a parsed object.

```js
import getRawBody from "raw-body";

const JWKS = jose.createRemoteJWKSet(
  new URL("https://your-store.saleor.cloud/.well-known/jwks.json")
);

// In Next.js you need to disable `bodyParser` in order to get raw body string
// https://github.com/vercel/next.js/discussions/12517
export const config = {
  api: {
    bodyParser: false,
  },
};

export default function(req, res) {
  const jws = req.headers["saleor-signature"];
  const buffer = getRawBody(req, {
    length: req.headers["content-length"],
    limit: "1mb",
  });
  const [header, _, signature] = jws.split(".");
  try {
    await jose.flattenedVerify({
      protected: header,
      payload: buffer.toString("utf-8"),
      signature
    }, JWKS);
  } catch (e) {
    // return error
  }

  // handle your request
}
```
