Every n8n node that connects to an external service relies on a credential—an encrypted authentication object stored in the database using AES‑256‑CBC encryption with an instance‑unique key. The credential framework supports eight authentication schemes: OAuth2 (with automatic token refresh via lifecycle hooks), API Key, Basic Auth, Header Auth, Bearer Token, Query Auth, Digest Auth, and SSL Client Certificates. Webhook nodes, which expose public URLs, add four verification layers—HMAC‑SHA256 signature validation, IP allowlisting, built‑in authentication modes, and community security nodes—that collectively verify sender identity, integrity, and freshness [1] [2].
How do n8n credential nodes handle OAuth2, API keys, and vault integration?
n8n credential nodes implement the ICredentialType interface to define
authentication properties for each service. OAuth2 credentials
extend a base OAuth2 class with service‑specific parameters—Client ID, Client Secret,
scopes, and grant type—and n8n handles the full token lifecycle: redirect, obtain,
refresh automatically via lifecycle hooks, and encrypt storage. Users click
“Connect Account” in the credential panel to initiate the OAuth
flow for built‑in nodes; community nodes can implement the same interface.
[5]
[3]
API Key credentials store the key as an encrypted password field
(marked with typeOptions.password: true). For enterprise deployments,
external secrets vault integration retrieves secrets at runtime from
HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, or
Infisical via $secrets.<vault-name> expressions — decoupling
secrets from the database entirely. Self‑hosted users can also reference environment
variables in credential fields using $env:VARIABLE_NAME syntax, or
mount secrets from files via the _FILE suffix. For the complete
credential configuration reference with vault setup and environment variable patterns,
see the
n8n Credential Nodes guide.
How does the n8n credential system encrypt and protect stored secrets?
The credential system uses AES‑256‑CBC encryption to protect all
sensitive data at rest. The encryption flow starts when Credentials.setData()
receives a plaintext object—it validates the data is an object literal, encrypts
the entire JSON via Cipher.encrypt(), and stores the encrypted string
in this.data. On retrieval, Credentials.getData() decrypts
and returns the original plaintext. The encryption key is held in the
N8N_ENCRYPTION_KEY environment variable or the .n8n/config
file.
[1]
[6]
This key must remain constant across restarts and across all instances in a
queue‑mode cluster (main, workers, webhook instances)—changing it makes all existing
credentials permanently unreadable. For backup strategies, you must either back up
the .n8n/config file or preserve the encryption key value alongside
the database dump; without the original key, credential data in the backup is
unrecoverable. The system also implements data redaction to prevent exposing
secrets in the UI, project‑based sharing with role‑based access control
(owner/user), credential testing to validate authentication before use, and domain
restrictions to prevent unauthorized credential usage across different services.
For production credential management patterns including rotation and audit, see
the
credential nodes configuration guide.
How do you implement HMAC‑SHA256 signature verification for production webhooks?
HMAC‑SHA256 verification is the gold standard for webhook security. The canonical
six‑layer pattern chains: the Webhook node (Header Auth + Raw Body enabled), a
Code node extracts the raw body as a UTF‑8 string, a Crypto node computes
HMAC‑SHA256(timestamp.rawBody), a Code node performs
timing‑safe comparison using crypto.timingSafeEqual(),
a payload validation node whitelists expected JSON fields and rejects unexpected
keys, then business logic executes only after all checks pass.
Invalid requests return 403 Forbidden (signature/timestamp
failure) or 400 Bad Request (payload validation failure), with
no response body to avoid leaking internal logic.
[2]
For replay protection, include a timestamp and optional nonce in the signed
payload; the Code node rejects any request with a timestamp older than a
configurable window (default: 5 minutes). While n8n’s built‑in Webhook
authentication modes (Basic Auth, Header Auth, JWT) verify who
is calling, they do not verify that the payload hasn’t been
altered or that the request is fresh. The community Secure Webhook
node (@prokodo/n8n-nodes-secure-webhook) bundles all six layers—
plus IP allow/deny policies and per‑IP rate limiting—into a single hardened
trigger [7].
For complete webhook authentication and payload validation walkthroughs, see the
n8n Webhook Node Security guide.
How does IP allowlisting work on the Webhook node, and what are its limits?
IP allowlisting on the Webhook node restricts access to specific IP ranges
configured as comma‑separated CIDR entries (e.g., 34.195.0.0/16,
54.208.0.0/15). Requests from IPs outside the list are rejected before
the workflow executes, adding a network‑layer filter that complements
application‑layer authentication for defense‑in‑depth. However, IP allowlisting
should never be the sole security layer.
[8]
A critical vulnerability: CVE‑2025‑68949 (CVSS 5.3 MEDIUM) affected n8n versions 1.36.0 through <2.2.0, where the Webhook node’s IP whitelist performed partial string matching instead of exact IP comparison. An attacker whose IP shared a partial prefix with a whitelisted address could bypass restrictions—both IPv4 and IPv6 were impacted. The fix shipped in version 2.2.0. [4] Always upgrade if you use IP allowlisting, and layer it with HMAC signature verification or JWT authentication. For the complete guide to webhook hardening combining IP filters with cryptographic verification, see the n8n Webhook Node Security guide.
How do you harden self‑hosted n8n nodes with environment variables and a reverse proxy?
Production‑grade self‑hosted hardening requires multiple layers. Basic
Auth (N8N_BASIC_AUTH_ACTIVE=true with
N8N_BASIC_AUTH_USER/N8N_BASIC_AUTH_PASSWORD) adds a
login wall to the n8n UI and REST API—the recommended minimum layer before
exposing n8n to the internet. It does not protect public
webhooks, which must be secured separately with HMAC, API keys, or custom
validation inside workflows.
[9]
For Code‑node isolation, set N8N_BLOCK_ENV_ACCESS_IN_NODE=true to
prevent Code nodes from accessing process.env, and exclude high‑risk
nodes (ExecuteCommand, LocalFileTrigger) via NODES_EXCLUDE. For
webhook URL security, bind n8n to 127.0.0.1:5678 so port 5678
is never directly exposed—all external traffic must pass through a reverse proxy
(Nginx or Caddy) that terminates HTTPS and forwards
X‑Forwarded‑For and X‑Forwarded‑Proto headers. Set
N8N_PROXY_HOPS=1 so n8n correctly identifies the real client IP
for IP allowlisting. Always pin Docker image versions (e.g.,
n8nio/n8n:2.17.7) instead of using latest, and store
TLS certificates via certbot with Let’s Encrypt for auto‑renewal. For the
complete self‑hosted hardening blueprint covering firewall rules, audit logging,
and backup strategies, see the
n8n Node Security Hardening guide.
References
- DeepWiki — Credential System: AES‑256‑CBC encryption, ICredentialType interface, encryption/decryption flow, 8 auth schemes, OAuth2 token lifecycle
- n8n Workflow Template — Secure AI Agent Webhook with HMAC, Replay Protection, and OpenAI GPT‑5: six‑layer security chain, timing‑safe comparison, strict payload validation
- DeepWiki — Credential Management and Sharing: N8N_ENCRYPTION_KEY, storage architecture, project‑based sharing with RBAC, external secrets vault integration
- NIST NVD — CVE‑2025‑68949: n8n Webhook Node IP Whitelist Bypass via Partial String Matching (1.36.0 to <2.2.0), CVSS 5.3 MEDIUM, fixed in 2.2.0
- n8n Community — Connect n8n workflows with external APIs that require OAuth2: built‑in node support, “Connect Account” flow, community node credential implementation
- n8n Community — Help understand n8n credentials encryption for backup: N8N_ENCRYPTION_KEY storage, config file vs environment variable, backup considerations
- @prokodo/n8n-nodes-secure-webhook v0.0.1 — Community hardened webhook trigger: HMAC/JWT/JWKS/API Key auth, replay protection, IP allow/deny (CIDR), per‑IP rate limiting, Redis HA, mTLS header checks, audit export
- n8n Documentation — Webhook Node: HTTP methods, authentication (Basic, Header, JWT), response modes, IP allowlisting (CIDR), raw body option
- RapidDevelopers — How to secure n8n with basic auth: N8N_BASIC_AUTH_ACTIVE, editor + API protection, webhook exemption, HTTPS requirement, Docker Compose setup

