Skip to content
nviaOTP

Webhooks & HMAC Signing · Chapter 5 of 5

Rotating secrets

A zero-downtime rotation procedure, with overlapping secrets and a clear rollback.

9 min read

Secrets leak: an engineer pastes one into a ticket, a config file ends up in a public repository, a vendor is breached. You need to rotate without dropping a single webhook — which means a period where two secrets are valid at once.

The overlap procedure

  • Generate the new secret in the provider dashboard. Most providers then sign with both secrets, emitting two v1= values.
  • Deploy your endpoint with both secrets in its active list. Verification passes if any signature matches any secret.
  • Watch metrics until 100% of verifications succeed against the new secret.
  • Expire the old secret at the provider, then remove it from your config.
const ACTIVE = [process.env.WH_SECRET_NEW, process.env.WH_SECRET_OLD].filter(Boolean);

function verify(raw: string, header: Parsed) {
  return ACTIVE.some((s) =>
    header.signatures.some((sig) => safeEqualHex(hmac(s!, `${header.t}.${raw}`), sig)),
  );
}

Emergency rotation

If a secret is known to be compromised, skip the overlap: rotate at the provider and deploy the new secret immediately, accepting that in-flight webhooks during the deploy will fail and be retried. Afterwards, audit events received in the exposure window — a forged verified event is the one that matters.

Discussion · 0