# Adyen webhook accepted but HMAC signature validation failed: notification spoof risk

## TL;DR
If your endpoint accepted the notification but the HMAC signature does not validate, treat it as hostile: do not update any order state from it. Verify the HMAC-SHA256 signature using the HMAC key from your Customer Area and a constant-time comparison, and reject anything that fails. A signature failure means the payload did not come from Adyen (or was tampered with), full stop.

```text
adyen webhook accepted but HMAC signature validation failed: notification spoof risk
```

## Steps

1. Stop trusting the payload immediately. Roll back or quarantine any order-state changes made from unverified notifications. Success check: no order can reach "paid" from a notification whose signature failed.

2. Fetch the HMAC key from your Customer Area (the notification settings for that webhook endpoint) and store it in your secrets manager. Never commit it to source control. Success check: the key is loaded from secrets at runtime, not hardcoded.

3. Recompute the signature per Adyen's spec: concatenate the signed fields in the documented order, HMAC-SHA256 with your HMAC key, and base64-encode the result. Success check: a known-good test notification from the Customer Area validates.

4. Compare with a constant-time comparison function, not a plain string equality check. Success check: verification code uses a timing-safe compare.

5. Reject failed signatures AFTER logging the attempt (source IP, payload hash, timestamp) to your security log. Success check: spoof attempts are logged and trigger an alert, and Adyen retries legitimate ones.

## When this applies

- Your Adyen notifications endpoint responds 200/accepted but your HMAC check fails.
- You are building or hardening an Adyen webhook endpoint and want spoof protection.
- You suspect notification tampering or replay attacks.

## When it doesn't

- Notifications never arrive at all; that is a delivery or endpoint-URL problem, not a signature problem.
- Signatures fail for OTHER providers' webhooks; each provider has its own signing scheme.
- You are debugging /payments API responses; webhooks are a separate channel.

## Tool + version compatibility

Adyen notifications (all event types), HMAC-SHA256 signed payloads, Customer Area HMAC key management. Applies to both live and test endpoints.

### "adyen hmac validation failed webhook"
The core issue. Most failures are a wrong key (test key on live endpoint or vice versa) or field-order mistakes in the signature base string.

### "adyen notification signature invalid"
Check that you are signing the exact field values as received, with no JSON re-serialization in between.

### "adyen webhook spoofing"
This is the threat the HMAC exists to stop. Unverified notifications must never move money or mark orders paid.

## Why it happens

Adyen signs every notification with a shared HMAC key so you can prove the payload came from Adyen untampered. Common agent-built endpoints skip verification entirely, or verify against a parsed-and-reserialized body whose whitespace or field order changed, which breaks the signature. Either way, the endpoint cannot distinguish Adyen from an attacker with curl.

## Edge cases / pitfalls

- Test and live HMAC keys are different. Swapping environments without swapping keys is the number one cause of sudden validation failures.
- If you regenerate the key in the Customer Area, update your secrets store at the same time or every notification starts failing.
- Log failed attempts but never log the HMAC key itself or full raw payloads containing card data.
- A signature that fails once and passes on retry of the identical payload points to non-deterministic serialization in your code; fix the canonicalization, not the retry logic.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_ZF9He9ZoVbn6Obmew3k7mA
