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

# Signaturen verifiëren

> Beveilig je webhooks door bij elk verzoek de HMAC-signatuur te controleren. Bevestig dat payloads van storekit komen en onderweg niet zijn gemanipuleerd.

Het verifiëren van webhook-signaturen is essentieel voor de beveiliging. Zo weet je zeker dat de webhook echt van storekit komt en niet is gemanipuleerd.

## Waarom verifiëren?

Omdat je webhook-endpoint publiek toegankelijk is, kan iedereen verzoeken sturen en zich voordoen als storekit. Signatuurverificatie voorkomt:

* **Vervalste verzoeken**: Aanvallers die valse webhooks versturen
* **Replay-aanvallen**: Oude webhooks die kwaadwillig opnieuw worden verstuurd
* **Datamanipulatie**: Wijzigingen aan webhook-payloads onderweg

## Svix-bibliotheken gebruiken (aanbevolen)

We raden aan om voor verificatie de officiële Svix-bibliotheken te gebruiken; die nemen alle complexiteit voor je uit handen:

<CodeGroup>
  ```javascript Node.js theme={null}
  import { Webhook } from 'svix';

  const wh = new Webhook(process.env.WEBHOOK_SECRET);

  try {
    const payload = wh.verify(rawBody, headers);
    // Process the verified payload
  } catch (err) {
    // Signature verification failed
    return res.status(400).send('Invalid signature');
  }
  ```

  ```python Python theme={null}
  from svix.webhooks import Webhook

  wh = Webhook(os.environ['WEBHOOK_SECRET'])

  try:
      payload = wh.verify(raw_body, headers)
      # Process the verified payload
  except Exception as e:
      # Signature verification failed
      return Response(status=400)
  ```

  ```go Go theme={null}
  import svix "github.com/svix/svix-webhooks/go"

  wh, _ := svix.NewWebhook(os.Getenv("WEBHOOK_SECRET"))

  err := wh.Verify([]byte(rawBody), headers)
  if err != nil {
      // Signature verification failed
      return
  }
  ```
</CodeGroup>

<Warning>
  Gebruik voor verificatie altijd de ruwe request-body. Als je de JSON eerst parseert en daarna weer stringifyt, komt de signatuur niet overeen door mogelijke formatteringsverschillen.
</Warning>

## Handmatige verificatie

Als je liever handmatig signaturen verifieert zonder de Svix-bibliotheek te gebruiken, volg dan de onderstaande stappen.

### Signatuur-headers

Elke webhook bevat deze headers voor verificatie:

| Header           | Beschrijving                                                  |
| ---------------- | ------------------------------------------------------------- |
| `svix-id`        | Unieke berichtidentifier                                      |
| `svix-timestamp` | Unix-timestamp van het moment waarop het bericht is verstuurd |
| `svix-signature` | De signatuur(en) om tegen te controleren                      |

## Verificatiestappen

### 1. Headers extraheren

```javascript theme={null}
const svixId = request.headers['svix-id'];
const svixTimestamp = request.headers['svix-timestamp'];
const svixSignature = request.headers['svix-signature'];
```

### 2. Timestamp verifiëren (replay-aanvallen voorkomen)

Weiger webhooks met een timestamp ouder dan 5 minuten:

```javascript theme={null}
const tolerance = 5 * 60; // 5 minutes in seconds
const now = Math.floor(Date.now() / 1000);
const timestamp = parseInt(svixTimestamp, 10);

if (Math.abs(now - timestamp) > tolerance) {
  throw new Error('Webhook timestamp too old');
}
```

### 3. Ondertekende inhoud opbouwen

Voeg de webhook-ID, timestamp en body samen:

```javascript theme={null}
const signedContent = `${svixId}.${svixTimestamp}.${rawBody}`;
```

### 4. Verwachte signatuur berekenen

Gebruik HMAC-SHA256 met je webhook-secret:

```javascript theme={null}
const crypto = require('crypto');

// Your secret from the dashboard (remove the 'whsec_' prefix)
const secret = Buffer.from(secretKey.split('_')[1], 'base64');

const expectedSignature = crypto
  .createHmac('sha256', secret)
  .update(signedContent)
  .digest('base64');
```

### 5. Signaturen vergelijken

```javascript theme={null}
const signatures = svixSignature.split(' ');
const isValid = signatures.some(sig => {
  const [version, signature] = sig.split(',');
  return version === 'v1' && signature === expectedSignature;
});

if (!isValid) {
  throw new Error('Invalid webhook signature');
}
```


## Related topics

- [Webhooks-overzicht](/docs/nl/developers/webhooks/overview.md)
- [Introductie voor ontwikkelaars](/docs/nl/developers/introduction.md)
- [Google Tag Manager & Meta Pixel](/docs/nl/guides/integrations/marketing/google-tag-manager.md)
- [Kostenrapport & Daily Summary](/docs/nl/guides/reports/fee-report.md)
- [storekit Payments instellen](/docs/nl/guides/payments/storekit-payments-setup.md)
