HMAC for API Request Signing
How to use HMAC-SHA256 to sign API requests — AWS Signature v4, webhook verification, and custom signing.
Published:
Tags: HMAC API signing, API request signing HMAC, webhook HMAC verification
HMAC for API Request Signing HMAC-SHA256 is the standard mechanism for authenticating API requests and webhook events. It proves that a request came from someone with the shared secret and that the body was not modified in transit. This guide covers request signing patterns, webhook verification, AWS Signature Version 4, and replay attack prevention. --- Why Sign API Requests? API keys alone are vulnerable to interception — if an API key leaks, any request with that key is authenticated. HMAC signing adds message-level authentication: Integrity: the request body cannot be modified after signing Authentication: the requester holds the secret key Replay protection: timestamps prevent reuse of captured requests This is why payment processors, cloud providers, and webhook systems all use HMAC…
Frequently Asked Questions
How do I use HMAC to sign API requests?
Construct a canonical string representing your request (method, path, timestamp, body hash), then compute HMAC-SHA256 over this string using a shared secret. Send the timestamp and signature in request headers. On the server, reconstruct the same canonical string, compute the HMAC with the stored secret, and compare using constant-time equality. Reject requests where the timestamp is more than 5 minutes old.
What is AWS Signature Version 4?
AWS SigV4 is Amazon's HMAC-SHA256 based request signing scheme used for all AWS API calls. It signs a canonical request (hashed payload, headers, path) with a key derived from your secret key, service name, region, and date. The derived signing key changes daily. AWS SDKs handle SigV4 automatically, but understanding the algorithm is useful for debugging authentication failures.
How do I verify HMAC in webhook handlers?
Most webhook providers (Stripe, GitHub, Twilio) send an HMAC-SHA256 signature of the request body in a header. On receipt: extract the signature from the header, compute HMAC-SHA256 of the raw request body using the webhook secret, compare using constant-time equality. Use the raw body (before JSON.parse) — parsing modifies whitespace and may change the hash.
How do I prevent replay attacks with HMAC?
Include a timestamp (Unix epoch, seconds) in the signed string. On the server, reject requests where the timestamp differs from server time by more than 5 minutes (typically). Optionally store a nonce cache of recently seen nonces to reject duplicate requests within the window. Stripe uses this approach: the `Stripe-Signature` header includes `t=timestamp` and `v1=signature`.
What is a timing-safe HMAC comparison?
A timing-safe comparison takes the same amount of time regardless of where the strings differ. Regular string comparison (`===`) returns early when it finds the first difference, leaking the number of matching characters. Over many requests, an attacker can brute-force the expected signature one byte at a time. Use `crypto.timingSafeEqual()` in Node.js, `hmac.compare_digest()` in Python, or `hash_equals()` in PHP.
All articles · theproductguy.in