n8n browser OAuth2 webhook auth vs Sume HMAC-signed webhooks

n8n 2.42 adds a browser OAuth2 flow for User Auth webhooks. Sume's webhooks are server-to-server and HMAC-signed instead. A Python verifier that fails closed.

5 min readSume
All posts

n8n's new browser OAuth2 flow for User Auth webhooks authenticates a person in a browser, and Sume's webhooks are sent by a server with no person present, so the two do not meet. Sume authenticates its deliveries with an HMAC signature that your endpoint verifies, not with a login. The 2.42.0 release (2026-09-29) lists the browser OAuth2 flow among its notable changes (read 2026-10-03), so if you were about to put that auth on the webhook that Sume calls, do not.

The n8n item is in the 2.42.0 release notes. The Sume scheme is in Webhooks and Run webhooks.

What Sume sends and what proves it

A Sume delivery is one POST with a JSON body and two headers: x-sume-webhook-timestamp and x-sume-webhook-signature. The signature is sume-v1= followed by the hex HMAC SHA-256 of <timestamp>.<raw_body> under your signing secret. During a secret rotation the header carries one entry per live secret, newest first, separated by commas, and you accept the delivery when any sume-v1= entry matches. Reject a timestamp outside your replay window; Sume suggests five minutes.

The secret is on the Webhooks tab of the dashboard, or from GET /v1/webhooks/signing-secret with an API key carrying account:read. One verifier covers both job webhooks and run webhooks.

Two kinds of webhook auth, read 2026-10-03
Propertyn8n User Auth webhook (browser OAuth2)Sume delivery
Who callsA person in a browserSume's servers
ProofAn OAuth2 loginHMAC sume-v1= signature plus timestamp
Replay defenseSession handlingTimestamp window you enforce
RetriesNot applicableUp to 10 attempts; Redeliver after

A verifier that fails closed

n8n's Webhook node can hand you the raw body if configured to, and the signature is computed over the raw bytes, so verify before any parsing that re-serializes the JSON. The function below refuses an empty secret, checks the timestamp window, and compares every sume-v1= entry in constant time.

import hashlib, hmac, time

def verify_sume(raw_body: bytes, timestamp: str, header: str,
                secret: str, tolerance: int = 300) -> bool:
    if not secret:
        raise ValueError("signing secret is empty; refusing to verify")
    try:
        ts = int(timestamp)
    except ValueError:
        return False
    if abs(int(time.time()) - ts) > tolerance:
        return False
    digest = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body,
                      hashlib.sha256).hexdigest()
    expected = f"sume-v1={digest}"
    ok = False
    for entry in header.split(","):
        if hmac.compare_digest(entry.strip(), expected):
            ok = True
    return ok

if __name__ == "__main__":
    body, ts, sec = b'{"event":"job.completed"}', str(int(time.time())), "test-secret"
    sig = "sume-v1=" + hmac.new(sec.encode(), f"{ts}.".encode() + body,
                                hashlib.sha256).hexdigest()
    print(verify_sume(body, ts, sig, sec), verify_sume(body, ts, sig, "other"))

Wiring it into n8n

Leave the Sume-facing webhook path without User Auth, since a browser flow cannot complete for a server caller, and put the signature check first in the workflow, in a Code node or an HTTP step to a small verifier. If the check fails, return an error status and stop. Use job_id as the idempotency key in downstream steps, because a retry or a Redeliver can send the same event again; Redeliver does not consume one of the automatic ten attempts.

Respond with a 2xx quickly. Sume gives each attempt 10 seconds, and a slow endpoint burns the budget and gets retried. Do the real work after you acknowledge, and keep the secret in n8n credentials, not in the workflow JSON you export and share.

Testing the receiver without spending

Test before connecting real jobs. Sume's webhooks page describes Send test and Redeliver, so you can have a delivery sent to your endpoint without waiting for a job, and a Redeliver re-POSTs a stored delivery with a fresh timestamp and signature. Use them to confirm three cases: a valid delivery passes, a body altered by one character fails, and a request with an old timestamp fails.

If a valid delivery fails, the cause is almost always the body. Frameworks that parse JSON and re-serialize it change whitespace and key order, and the signature covers the raw bytes. Capture the raw body before parsing. The second most common cause is the wrong secret, and Sume exposes a fingerprint header, x-sume-webhook-secret-fingerprint, so you can compare the fingerprint with the one in the dashboard without sending the secret anywhere.

Once it passes, rotate the signing secret in a staging account and confirm your verifier accepts the comma-separated header with two entries during the overlap.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume