Skip to content
New: a free website for your business, live in 48 to 72 hoursWorkflow automation on n8n and Claude, built for your businessFixed price, agreed before we start · Live in 5 to 10 business days30-day money-back guarantee on every planProfessional firms · Agencies · E-commerceYou own every workflow, in your own n8nClaude API: your data is not used for trainingHuman approval on every sensitive stepFree automation audit, no obligation
PURIST
30 days
Money-back window
14 h/wk
Modeled time saved
99.97%
Uptime SLA
< 7 days
Deploy time
PURIST AI
Claude Opus 4.7 · n8n v1.71 · <80ms
What type of business are you running? I'll show you exactly which processes we'd automate first and your estimated ROI.
Powered by n8n + Claude Opus 4.7 Get my free automation plan →
Secure an n8n Webhook: Header Auth, Basic Auth, JWT and HMAC Signatures
Guides 8 min read · 1,696 words

Secure an n8n Webhook: Header Auth, Basic Auth, JWT and HMAC Signatures

An n8n webhook URL with no authentication accepts requests from anyone who finds it. Five layers of protection, from a header secret to HMAC signature checks, and which to use for each sender.

Steve, founder of PURIST

November 6, 2026

PURIST: Stuck on n8n? Our n8n experts fix and build workflows like this one, at a fixed price →

A production webhook URL is public by nature: anyone who learns it can send requests, and your workflow will happily create fake leads, send emails or write to your CRM. Purist found exactly this pattern on its own site in October 2026: bots submitting forms with harvested real email addresses. n8n gives you several ways to reject requests that do not come from the sender you expect.

In short. Turn on the Webhook node's Authentication (Header Auth is the simplest for systems you control). For providers that sign their requests (Stripe, Shopify, GitHub and many others), verify the HMAC signature in a Code node using the raw body. Add the IP(s) Allowlist when the sender publishes fixed IPs, and Ignore Bots for public form endpoints.

Secure an n8n Webhook: Header Auth, Basic Auth, JWT and HMAC Signatures: workflow diagram
Layers of protection before a request reaches your workflow: authentication, signature check, validation. Illustration: PURIST.

Layer 1: built-in authentication

The Webhook node supports Basic auth, Header auth, JWT auth, n8n User Auth (OAuth2) and None. Requests that fail are rejected before your workflow runs.

MethodHow the caller proves itselfBest for
Header AuthSends a secret header, for example X-Api-Key: ...Your own apps, scripts, other n8n instances
Basic AuthSends a username and passwordTools that only support basic auth
JWT AuthSends a signed JSON Web TokenApps that already issue JWTs
n8n User Auth (OAuth2)Bearer token issued by your n8n instanceInternal tools used by logged-in n8n users

Setting up Header Auth:

  1. 1 In the Webhook node, set Authentication to Header Auth.
  2. 2 Create a credential: Name X-Api-Key, Value a long random secret. Our free secret key generator makes one in your browser.
  3. 3 Give the same header and value to the system that calls the webhook.
bash
curl --request POST https://n8n.example.com/webhook/new-lead \
  --header 'X-Api-Key: YOUR_LONG_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{"email":"test@example.com"}'

Layer 2: verify provider signatures (HMAC)

Payment and commerce platforms do not let you add custom headers. Instead they sign each request: they compute an HMAC of the body with a shared secret and send it in a header. You recompute it and compare. If it differs, the request is fake or was altered.

Two settings matter:

  1. 1 Turn on the Webhook node option Raw Body. Signatures are computed on the exact bytes received; a re-serialised JSON body will not match.
  2. 2 Keep the secret out of the code. Store it where your instance allows (for example an environment variable read with $env, if your admin permits it).

Generic verification in a Code node placed right after the Webhook:

javascript
const crypto = require('crypto');
const item = $input.first();
const secret = $env.WEBHOOK_SIGNING_SECRET;
const received = item.json.headers['x-signature'] || '';
const raw = await this.helpers.getBinaryDataBuffer(0, 'data');
const expected = crypto.createHmac('sha256', secret).update(raw).digest('hex');
const ok = received.length === expected.length &&
  crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!ok) throw new Error('Invalid webhook signature');
return [item];

Adjust three things to your provider, from its documentation: the header name, the algorithm (usually SHA-256), and the encoding (hex or base64). Some providers sign a string that includes a timestamp, which also lets you reject old replayed requests. With Raw Body on, the Webhook node puts the exact bytes received in the binary property data, which is what the code above reads. Before you wire it, paste a sample payload and secret into our free Webhook Signature Verifier to confirm you compute the same value as the provider.

Secure an n8n Webhook: Header Auth, Basic Auth, JWT and HMAC Signatures: node settings
Webhook node settings for a production endpoint: Header Auth, Raw Body, IP allowlist, Ignore Bots. Illustration: PURIST.

Layer 3: restrict who can call

  • IP(s) Allowlist: a comma-separated list of IPs allowed to call the webhook. Others receive a 403. Behind a reverse proxy, set N8N_PROXY_HOPS to the number of proxies, otherwise n8n sees the proxy's IP and blocks everyone.
  • Ignore Bots: ignores link previewers and crawlers, useful when a URL might be pasted in chats.
  • Allowed Origins (CORS): restrict which websites can call the webhook from a browser. Default * allows all.

Layer 4: filter before running

The Only Run If option evaluates an expression on the request ($json contains body, headers, params and query). Non-matching requests get a 200 response without creating an execution. Example:

text
{{ $json.body.campaign_id === 'spring-offer' }}

It is a filter, not authentication: anyone can guess a field value. Use it to drop noise on top of real authentication.

Layer 5: validate the content

Even an authenticated sender can send bad data. Add an IF node that checks required fields and formats, and answer 400 with a clear message through a Respond to Webhook node. For public forms, add a honeypot field and reject submissions that fill it.

Worked example: a public website form that bots cannot abuse

A form on your website posts to an n8n webhook that creates a CRM lead and sends a welcome email. You cannot hide a secret in a browser, so Header Auth alone does not help: anyone can read the page source. Here is the layered setup we use on purist.online after bots submitted fake leads with harvested real addresses in October 2026.

  1. 1 Honeypot field. Add a hidden input (for example company_website) that humans never fill. Bots fill every field.
  2. 2 Timing. Record when the form was displayed and send the elapsed time with the submission. Humans need several seconds to type; bots post instantly.
  3. 3 Human input signal. Send a flag only if a real key press, click or touch happened on the page.
  4. 4 Content check. Reject random strings in name fields.
  5. 5 Same response either way. Answer 200 to rejected requests too, so bots learn nothing, but do not store or email them.

In n8n, the first node after the Webhook is an IF node that combines these checks:

text
{{ !$json.body.company_website && Number($json.body.elapsedMs) > 2500 && $json.body.humanInput === true }}

The true branch runs the real workflow. The false branch goes straight to a Respond to Webhook node returning {"success":true} and nothing else. In our tests after deploying it, a simulated bot submission created no record and sent no email, while a real visitor went through normally.

Verifying a provider signature: the three details that break it

Most failed signature checks come from one of these:

  1. 1 Parsed body instead of raw body. JSON.stringify($json.body) rarely reproduces the exact bytes the provider signed: key order and spacing change. Turn on Raw Body and hash the raw bytes in binary.data.
  2. 2 Wrong encoding. Some providers send hex, others base64, some prefix the value (for example sha256=...). Strip the prefix and compare in the same encoding.
  3. 3 Timestamped signatures. Some providers sign timestamp + "." + body and send the timestamp in a header. Rebuild exactly that string, and reject requests older than a few minutes to block replays.

A constant-time comparison (crypto.timingSafeEqual) avoids leaking information through response timing. Check that both buffers have the same length first, or it throws.

Which protection for which sender

SenderRecommended protection
Your own backend or scriptHeader Auth with a long random secret
Another n8n instanceHeader Auth, plus IP allowlist if its IP is fixed
Stripe, Shopify, GitHub and similarSignature verification on the raw body
Public website formHoneypot, timing, human input signal, content checks
Internal tool used by your teamn8n User Auth (OAuth2)
SaaS without signatures or custom headersSecret token in the path or query, plus IP allowlist if published

Troubleshooting table

SymptomLikely causeFix
Every request gets 403Wrong header name or value, or allowlistCompare exactly; check N8N_PROXY_HOPS
Signature never matchesHashing the parsed bodyEnable Raw Body, hash binary.data
Signature matches in test, fails liveDifferent secret for test and live modeUse the live signing secret in production
Bots still get throughOnly auth on a public formAdd honeypot, timing and content checks
Legit requests rejected after a proxy changeProxy hops changedUpdate N8N_PROXY_HOPS

Production checklist

  • Authentication on every production webhook, no exceptions.
  • Signature verification for every provider that signs requests.
  • Secrets stored in credentials or environment, never in the workflow.
  • A custom, non-guessable path.
  • An error workflow that alerts you when verification fails repeatedly.
  • Rotate the secret when someone with access leaves.

Frequently asked questions

Is an n8n webhook secure by default?

No. With Authentication set to None, anyone with the URL can trigger it. Enable Header, Basic or JWT auth, and verify signatures for providers that sign requests.

How do I verify a Stripe or Shopify signature in n8n?

Enable Raw Body on the Webhook node, then recompute the HMAC of the raw body with your signing secret in a Code node and compare it to the signature header using a constant-time comparison. Each provider documents its header and format.

Why does my IP allowlist block every request?

n8n probably sees your reverse proxy's IP. Set N8N_PROXY_HOPS to the number of proxies in front of n8n.

Does Only Run If replace authentication?

No. It filters requests by content. Use it in addition to authentication, not instead of it.

Can I put a secret in the webhook URL instead of a header?

It works for senders that cannot set headers, but URLs end up in logs. Prefer headers or signatures, and rotate URL secrets periodically.

How do I block old replayed requests?

Use providers' timestamped signatures: rebuild the signed string with the timestamp and reject requests older than a few minutes.

Does n8n log rejected webhook requests?

Requests rejected by authentication do not create executions. Check your reverse proxy logs to see them.

Tags

n8nwebhooksecurityhmacauthentication
Steve, founder of PURIST

Steve founded PURIST, a workflow automation studio working with n8n, Make and Claude AI, and is the point of contact on every project. Prices and features in our articles come from vendor documentation and public pricing pages. How we research and score tools.

Complete guide

Automation Tools & Platforms

11 min read n8n Code Node: 15 JavaScript Examples You Can Copy and … 8 min read n8n Code Node With Multiple Inputs: 3 Methods That Work 7 min read Fix "Cannot find module" in the n8n Code Node (npm Pack… 7 min read n8n Code Node Errors Fixed: "Code doesn't return items … 7 min read $env and Credentials in the n8n Code Node: What Works a… 7 min read n8n Code Node Binary Data: Read, Change and Return File… 7 min read Python in the n8n Code Node (n8n 2.x): Setup, Syntax an… 7 min read Fix n8n "The requested webhook is not registered" (Test… 6 min read n8n Webhook URL: Test vs Production, and How to Change … 7 min read n8n Respond to Webhook: Return JSON, Status Codes, Redi… 7 min read n8n Webhook Not Working? 10 Causes and How to Fix Each … 7 min read n8n HTTP Request Pagination: Every Pattern With Working… 7 min read n8n HTTP Request Authentication: API Keys, Bearer Token… 7 min read n8n HTTP Request Timeout and "Aborted" Errors: Causes a… 7 min read Upload and Download Files With the n8n HTTP Request Nod… 6 min read Fix ECONNREFUSED in n8n: Docker, localhost and 127.0.0.… 6 min read n8n 429 Too Many Requests: Batching, Retries and Rate L… 6 min read Fix redirect_uri_mismatch for n8n OAuth2 Credentials (G… 7 min read n8n Expression Errors Fixed: "Referenced node is unexec… 6 min read Anatomy Claude skill: what it is, how to install it, an… 5 min read How to explain a business process with the Anatomy skil… 5 min read Anatomy vs Mermaid vs Excalidraw: which to explain a wo… 14 min read n8n LinkedIn Job Automation: Auto-Apply, Track, and Fol… 16 min read n8n HTTP Request Node: Complete Documentation and Examp… 18 min read The future of automation: how our engineering team is s… 8 min read n8n vs Make vs Zapier: the honest comparison your busin… 11 min read n8n vs Make vs Zapier: an honest comparison for product… 7 min read Webhook vs polling: the architecture decision that dete… 24 min read n8n tutorial: build your first production workflow in u… 26 min read The 9 best Zapier alternatives in 2026: an honest ranki… 21 min read Make.com tutorial: build powerful automations without c… 19 min read Automation consultant vs DIY: how to decide what is rig… 14 min read n8n Self-Hosted vs Cloud: The Complete Decision Guide (… 15 min read 5 Zapier Free Alternatives That Handle Real Production … 15 min read WhatsApp Business Automation With n8n: Build a 24/7 Cus… 17 min read Google Workspace Automation: 15 Workflows for Sheets, D… 16 min read Claude AI for Business Automation: What It Does, What I… 15 min read Airtable Automation With n8n: 10 Workflows That Make Yo… 15 min read Droven.io AI Automation Tools: Full Review and Best Alt… 14 min read Droven.io RPA and Business Automation: An Honest 2026 R… 15 min read Enterprise Workflow Automation: The Complete Guide for … 13 min read Document Workflow Automation: Software, Implementation,… 14 min read Marketing Automation Workflow: From Content Creation to… 16 min read Ad Campaign Workflow Data Model and SDR Inbound Pipelin… 14 min read ComfyUI Workflows for Business: Product Photography, Ma… 13 min read GPT-5.2 for Business Workflows and the spec-workflow-mc… 17 min read ServiceNow vs IBM BAW vs n8n: Enterprise Workflow Autom… 16 min read 9 Best Workflow Automation Tools for Small Business in …

Keep reading

More from the blog.

All articles

From audit to deployment

Experience the automation
these articles are about.

Get my free automation plan →