BenchmarksStack Ranking
APIsPricingDocsWhite PaperTokenBlogAboutSecurity Demo
Log InGet API Key
Tutorial · 5 min read

H33 Webhooks:
Real-Time Authentication Events

How to implement and handle H33 authentication webhooks.

5 min
Setup
Open
Source
SDK
Ready
Production
Grade

Every modern authentication platform needs a way to push events to downstream services in real time. Polling an API for status changes is wasteful, fragile, and introduces latency that compounds across distributed systems. Webhooks solve this by inverting the communication model: instead of your service asking "did anything happen?", the authentication provider tells you the moment something does. At H33, where a single API call executes fully homomorphic encryption, zero-knowledge proof verification, and post-quantum attestation in under 42 microseconds, reliable webhook delivery is not optional -- it is load-bearing infrastructure.

What Are Webhooks and Why They Matter

A webhook is an HTTP callback: a POST request that an upstream service sends to a URL you control whenever a specific event occurs. In the context of authentication, this means events like auth.success, auth.failure, key.rotated, user.enrolled, and threat.detected. Your endpoint receives a JSON payload describing the event, processes it, and returns a 2xx status code to acknowledge receipt.

Event-driven architectures built on webhooks enable real-time audit logging, immediate anomaly response, downstream service orchestration, and compliance reporting without ever polling. For security-critical systems, the latency difference between a 30-second polling interval and a sub-second webhook delivery can be the difference between catching an attack in progress and discovering it in a post-mortem.

The Security Threat Model

Webhooks expose an HTTP endpoint on your infrastructure that accepts inbound traffic from the internet. This creates a well-defined attack surface that must be hardened against four primary threats:

AttackDescriptionMitigation
SpoofingAttacker sends forged payloads to your endpointHMAC signature verification
ReplayAttacker captures and re-sends a legitimate payloadTimestamp validation window
Man-in-the-MiddleAttacker intercepts and modifies payloads in transitTLS + signature verification
TimingAttacker uses response-time differences to leak secret dataConstant-time comparison

Every webhook implementation must address all four. Ignoring even one leaves your system vulnerable to exploitation. Let us walk through the defenses.

HMAC-SHA256 Signature Verification

The foundation of webhook security is cryptographic signature verification. When H33 sends a webhook, it computes an HMAC-SHA256 digest of the raw request body using a shared secret, and includes the result in the X-H33-Signature header. Your endpoint must recompute the same HMAC and compare. If they do not match, the payload was either forged or tampered with in transit.

Node.js Example

const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['x-h33-signature'];
  const timestamp  = req.headers['x-h33-timestamp'];

  // Replay protection: reject payloads older than 5 minutes
  const age = Math.abs(Date.now() / 1000 - parseInt(timestamp, 10));
  if (age > 300) {
    throw new Error('Webhook timestamp too old — possible replay');
  }

  // Compute HMAC over timestamp + body to bind them together
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${req.rawBody}`)
    .digest('hex');

  // Constant-time comparison to prevent timing attacks
  const sig = Buffer.from(signature, 'hex');
  const exp = Buffer.from(expected, 'hex');
  if (!crypto.timingSafeEqual(sig, exp)) {
    throw new Error('Invalid webhook signature');
  }

  return JSON.parse(req.rawBody);
}

Python Example

import hmac, hashlib, time, json

def verify_webhook(headers: dict, body: bytes, secret: str) -> dict:
    signature = headers['X-H33-Signature']
    timestamp = headers['X-H33-Timestamp']

    # Replay protection: 5-minute window
    if abs(time.time() - int(timestamp)) > 300:
        raise ValueError('Webhook timestamp expired')

    # Compute HMAC over timestamp.body
    expected = hmac.new(
        secret.encode(),
        f'{timestamp}.'.encode() + body,
        hashlib.sha256
    ).hexdigest()

    # Constant-time comparison
    if not hmac.compare_digest(signature, expected):
        raise ValueError('Invalid webhook signature')

    return json.loads(body)

Two critical details in both examples: the HMAC is computed over the concatenation of the timestamp and the raw body (separated by a period), which binds them together and prevents an attacker from swapping timestamps between payloads. And the comparison uses a constant-time function -- crypto.timingSafeEqual in Node, hmac.compare_digest in Python -- to eliminate timing side channels.

Replay Protection with Timestamp Validation

Even a perfectly signed payload can be dangerous if replayed. An attacker who captures a valid auth.success webhook could re-send it hours later, potentially granting unauthorized access if your system trusts it blindly. The defense is straightforward: include a Unix timestamp in the signed headers and reject any payload where the timestamp deviates from the current server time by more than five minutes. This window accounts for clock skew and network latency while keeping the replay surface minimal.

Idempotency Keys for Safe Retries

Networks are unreliable. H33 will retry webhook delivery with exponential backoff if your endpoint returns a non-2xx status code or times out. This means your handler must be idempotent -- processing the same event twice should produce the same result as processing it once. Every H33 webhook payload includes an idempotency_key field (a UUID v7 with embedded timestamp). Store this key in your database before processing, and skip any event whose key already exists.

Important

Always check the idempotency key before performing side effects. If you process the event first and then check for duplicates, a crash between processing and recording will cause the event to be processed again on retry.

Post-Quantum Webhook Signatures

A question that arises frequently: are HMAC-SHA256 webhook signatures vulnerable to quantum computers? The short answer is no. HMAC is a symmetric construction -- Grover's algorithm provides at most a quadratic speedup, reducing the effective security of HMAC-SHA256 from 256 bits to 128 bits. That is still astronomically beyond any foreseeable computational capability. Symmetric cryptography, including HMAC, AES, and SHA-3, is inherently quantum-resistant.

The vulnerability lies in asymmetric signatures. RSA and ECDSA, which many webhook providers use for payload signing, are completely broken by Shor's algorithm on a sufficiently large quantum computer. This is where H33 diverges from the industry standard.

H33's Webhook Architecture: Dilithium-Signed Payloads

H33 offers two verification modes for webhooks. The first is standard HMAC-SHA256 with a shared secret, as shown above -- simple, fast, and already quantum-safe. The second is Dilithium (ML-DSA) digital signatures on every payload, providing asymmetric post-quantum verification without shared secrets.

With Dilithium-signed webhooks, H33 signs the payload using its private ML-DSA key, and you verify it using H33's published public key. This eliminates the need to distribute and rotate shared secrets entirely, and it provides non-repudiation: you can cryptographically prove that H33 (and only H33) generated a given payload. This matters for compliance regimes that require irrefutable audit trails.

Verifying a Dilithium-Signed H33 Webhook

const { ml_dsa65 } = require('@h33/pqc');

async function verifyH33Webhook(req) {
  const payload   = req.rawBody;
  const signature = Buffer.from(req.headers['x-h33-dilithium-sig'], 'base64');
  const timestamp = req.headers['x-h33-timestamp'];

  // Replay protection
  if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) {
    throw new Error('Timestamp expired');
  }

  // Fetch H33 public key (cache this -- it rotates quarterly)
  const publicKey = await fetchH33PublicKey();

  // Verify ML-DSA-65 signature over timestamp.body
  const message = Buffer.from(`${timestamp}.${payload}`);
  const valid = ml_dsa65.verify(publicKey, message, signature);

  if (!valid) throw new Error('Invalid Dilithium signature');
  return JSON.parse(payload);
}
Why Dilithium?

Dilithium (ML-DSA) is the NIST-standardized post-quantum digital signature scheme, based on lattice hardness assumptions. H33 uses ML-DSA-65 (Level 3 security) for webhook signatures, providing 128+ bits of post-quantum security with signature sizes of approximately 3,293 bytes -- compact enough for HTTP headers.

Implementation Checklist

Before deploying your webhook handler to production, verify every item on this list:

  1. Verify signatures on every request. Never skip verification, even in staging. Use constant-time comparison functions exclusively.
  2. Enforce a 5-minute timestamp window. Reject any payload with a timestamp that deviates from your server clock by more than 300 seconds. Ensure your servers run NTP.
  3. Persist idempotency keys before processing. Use a unique constraint in your database on the idempotency key column. Check before executing side effects.
  4. Return 2xx quickly, process asynchronously. Acknowledge receipt immediately, then queue the event for processing. H33 will time out and retry after 10 seconds.
  5. Use TLS exclusively. Your webhook endpoint must be HTTPS. H33 will not deliver to plaintext HTTP URLs.
  6. Log raw payloads for forensics. Store the raw request body, all headers, and the verification result. This is critical for incident response and compliance audits.
  7. Rotate secrets proactively. If using HMAC mode, rotate your webhook secret at least quarterly. H33's dashboard supports dual-secret verification during rotation windows to prevent downtime.

Event Types Reference

EventTriggerPayload Fields
auth.successUser passes FHE biometric + ZKP verificationuser_id, confidence, latency_us, zkp_proof_id
auth.failureVerification fails threshold or ZKP checkuser_id, reason, attempt_count
key.rotatedAPI key or Dilithium keypair rotationkey_id, algorithm, effective_at
threat.detectedAI agent flags anomalous patternthreat_type, severity, source_ip, details
user.enrolledNew biometric template encrypted and storeduser_id, template_id, fhe_scheme

Every event payload includes a top-level event field, a timestamp (Unix seconds), an idempotency_key (UUID v7), and either an hmac or dilithium_signature depending on your configured verification mode.

Webhooks are deceptively simple in concept -- an HTTP POST with a JSON body -- but the security engineering required to handle them correctly in a production authentication system is substantial. Signature verification, replay protection, idempotent processing, and post-quantum readiness are not optional enhancements. They are the minimum bar. H33's dual-mode verification (HMAC-SHA256 for simplicity, Dilithium for post-quantum non-repudiation) gives you the flexibility to start simple and upgrade your security posture as quantum threats materialize, without changing your endpoint architecture.

Ready to Go Quantum-Secure?

Start protecting your users with post-quantum authentication today. 1,000 free auths, no credit card required.

Get Free API Key →

Build With Post-Quantum Security

Enterprise-grade FHE, ZKP, and post-quantum cryptography. One API call. Sub-millisecond latency.

Get Free API Key → Read the Docs
Free tier · 10,000 API calls/month · No credit card required
Verify It Yourself