The idea is:
Allow authenticating the n8n Public REST API (/api/v1/...) and Webhooknode endpoints with Authorization: Bearer <access_token>, where thetoken is a standard OAuth2 / OIDC access token issued by the sameIdentity Provider that is already configured underSettings → SSO → OIDC (e.g. Microsoft Entra ID, Okta, Keycloak,Auth0, Google Workspace OIDC, Ping).
Scope:
- Public API (
/api/v1/...) — primary ask. - Production webhook endpoints — a new “IdP OAuth2” authentication
option on the Webhook node, alongside the existing Header / Basic /
JWT options. - (Nice-to-have) The internal REST API, so scripts can reuse the
editor API with a bearer token.
Validation rules (reusing the IdP n8n already trusts for login):
- Fetch + cache JWKS from the IdP’s discovery document.
- Verify signature,
iss,aud,exp,nbfwith small clock-skew
tolerance. - Enforce an admin-configured expected audience (e.g.
api://n8n-api) — required, not optional, to prevent confused-deputy
where a token minted for a different app authenticates against n8n. - For client-credentials tokens: map
azp/appid/oidto a
dedicated service-principal identity in n8n with admin-configured
instance/project scopes (or derived fromroles/scopeclaims). - For user tokens (follow-up): resolve via the existing
AuthIdentity(providerType: 'oidc') mapping used by the login
flow, and reuseProvisioningService.applySsoProvisioningso role
claims behave consistently. - Existing
X-N8N-API-KEYcontinues to work unchanged — this is
additive, not a replacement.
Admin configuration (additive to the existing OIDC settings page):
Accept API calls with IdP bearer tokens— toggle.Expected audience(s)— array.Allowed client app IDs— array.Default instance/project role for service principals.Allow IdP OAuth2 auth on Webhook nodes— toggle.
My use case:
We run a self-hosted Enterprise n8n with OIDC SSO configured against
Microsoft Entra ID. The rest of our internal platform — APIs,
queues, databases, data-platform tooling — all accepts short-lived
Authorization: Bearer access tokens minted by Entra, with aud,
roles and conditional-access enforcement. n8n is the only
integration point that refuses those tokens and forces us to mint and
manage a parallel static secret.
A concrete example of what we want to do today and cannot:
-
In Entra, register an “n8n API” application exposing
api://n8n-apiwith app roles such asN8N.Workflow.Trigger. -
Register a daemon (“MyDaemon”) and grant it
N8N.Workflow.Trigger. -
MyDaemon performs a client-credentials grant:
POST https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token grant_type=client_credentials client_id=<MyDaemon client id> client_secret=<secret> scope=api://n8n-api/.default -
MyDaemon calls n8n with the resulting token:
POST /api/v1/workflows/<id>/run Authorization: Bearer eyJ... -
n8n returns 401, because the Public API only reads
X-N8N-API-KEY.
Same problem on webhooks: we would like a Webhook node that says
“authenticate callers via our Entra-minted bearer tokens”, but the
Webhook node only offers Header / Basic / JWT and none of them
validate against the configured SSO IdP.
Result: every service that needs to talk to n8n has to carry an n8n
API key provisioned out-of-band, and we cannot use the Entra
application lifecycle (disable app → access revoked) to control
access to n8n. We have to either mint static keys and accept the
compliance findings, or front n8n with an API gateway that validates
Entra tokens and substitutes an API key — losing per-caller identity
inside n8n and adding infra every operator has to reinvent.
With this feature:
- Same Entra setup, no new app registrations.
- n8n admin enables the new toggle, sets expected audience
api://n8n-api, allow-lists the MyDaemon client id. - The exact same curl call succeeds. Identity is traceable
(appid), scope is enforced (roles), and when the Entra admin
disables the MyDaemon app registration, access stops within the
token’s remaining lifetime — no manual key deletion in n8n.
I think it would be beneficial to add this because:
-
Security — short-lived vs. long-lived credentials. n8n API keys
are effectively forever. A leaked key (git commit, log line,
compromised CI runner, misrouted webhook echo) grants durable
access until a human notices and rotates it. IdP access tokens are
short-lived (typically 5–60 min); a leaked token is a bounded
window, not a permanent backdoor. -
Security — automatic, centralised revocation. Today, disabling
a service account in Entra does NOT revoke its n8n API key.
Offboarding a person does NOT invalidate their API keys. With
IdP-validated tokens, disabling the app registration / user in the
IdP stops the next token issuance and existing tokens expire on
their own within minutes. Revocation becomes a property of the
IdP, which is where it belongs. -
Security — inherited policy stack. Static API keys are a
single unauthenticated factor. IdP-minted tokens inherit everything
the IdP enforces on the caller: MFA, device compliance, conditional
access, location / geo / risk signals (Entra Identity Protection),
step-up auth, time-of-day policies. -
Auditability and forensics. API keys show up in audit logs as
an opaque label on a shared service account. IdP tokens carry a
realsub/appid/oid, so n8n audit logs can be correlated
one-to-one with IdP sign-in logs (Entra Sign-in logs, Okta System
Log) and the calling workload’s own logs. Much better for SOC /
incident response / SOC 2 / ISO 27001 evidence. -
Secret sprawl. API keys have to be stored by every caller
(Vault, Kubernetes Secrets, env vars, CI secrets, workstations).
Every storage location is a potential breach point and needs its
own rotation plumbing. Client-credentials and workload-identity
tokens can be acquired on-the-fly via platform identity (Entra
Managed Identity, AWS IRSA, GCP Workload Identity, SPIFFE / SPIRE)
— often with no long-term secret on the caller at all. -
Least privilege. n8n API keys are effectively “god mode for
that user” with no per-call scoping. IdP tokens carry
scope/rolesclaims that can be narrowed per caller and per
use case (e.g. a daemon only getsN8N.Workflow.Trigger, not
N8N.Admin). n8n can enforce those claims at the middleware
layer. -
Compliance. SOC 2, ISO 27001, PCI-DSS, HIPAA, FedRAMP all
expect centralised identity, short-lived credentials, and
auditable access. Long-lived per-app bearer tokens are a common
audit finding. Many regulated environments explicitly ban
long-lived bearer tokens for internal services; today those
enterprises can’t use n8n at all without putting a gateway in
front and losing per-caller identity inside n8n. -
Rotation in practice. Rotating an n8n API key is a manual,
coordinated event (rotate in n8n → update every consumer →
redeploy). Most orgs simply do not. IdP access tokens rotate
transparently every few minutes; the underlying client secret can
be rotated at the IdP with zero n8n-side changes; certificate-based
client auth removes even that secret. -
Zero-trust alignment. n8n is currently an outlier in any
zero-trust architecture: every other internal API accepts
short-lived IdP tokens withaudvalidation and least-privilege
scopes. Adding Bearer support on/api/v1and webhooks brings n8n
in line with standard enterprise practice. -
Low implementation cost. Most of the OAuth2 machinery is
already in the codebase (see Resources below). The delta is a
new middleware + a second security scheme in the OpenAPI spec +
a Webhook node auth option — not a new dependency or a redesign.
Any resources to support this?
Existing n8n code that already does 90% of what’s needed — this
feature is essentially “wire up what’s already there”:
packages/cli/src/modules/sso-oidc/oidc.service.ee.ts— already
performs OIDC discovery, caches theConfiguration, handles
HTTP(S) proxies, and uses theopenid-clientlibrary, which
exposes the JWKS / JWT verification primitives that this feature
would reuse. No new dependency required.packages/cli/src/modules/provisioning.ee/...—
ProvisioningService.applySsoProvisioningalready maps claims →
instance role → project roles. Can be reused directly.packages/cli/src/public-api/index.tsand
packages/cli/src/public-api/v1/openapi.yml— already use
express-openapi-validator, which supports multiple security
schemes. A newBearerAuthscheme can sit next toApiKeyAuth
without breaking any existing API-key client.packages/cli/src/modules/mcp/...— already implements the
“Bearer token via Express middleware” pattern; today it’s scoped
to n8n-issued tokens (aud=mcp-server-api), but it’s the exact
shape a sibling middleware for IdP-issued tokens would take.
Standards and references:
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token
Usage. - RFC 9068 — JSON Web Token (JWT) Profile for OAuth 2.0 Access
Tokens — audience,
claims, validation. - RFC 7523 — JWT Profile for OAuth 2.0 Client Authentication and
Authorization Grants. - RFC 8705 — OAuth 2.0 Mutual-TLS Client Authentication and
Certificate-Bound Access Tokens
(relevant as a future hardening step — sender-constrained tokens). - OAuth 2.0 Security Best Current Practice (draft-ietf-oauth-security-topics).
- Microsoft Entra: client-credentials grant.
- Microsoft Entra: access token claims (incl.
appid,azp,roles). - Okta: validate access tokens.
- OWASP: authentication cheat sheet — short-lived tokens &
revocation.
Community context:
- Existing forum thread: Integrate SSO credentials with node
credentials
— different ask, but confirms today’s limitation (“SSO in n8n is
currently only used to authenticate users into the UI”). - feat(core): Add OIDC support for SSO — PR
#15988 — the OIDC
foundation this proposal builds on. - feat(core): Allow changing the oauth token data for oauth2
credentials on public API PATCH — Issue
#25042 — adjacent
signal that “API access should follow IdP lifecycle” is a theme.
Caveats to be explicit about up front:
- Audience validation is mandatory (confused-deputy protection).
- Short JWKS cache TTL (few minutes) to follow IdP key rotation.
- Small clock-skew tolerance on
exp/nbf(~30 s). - No raw JWTs in logs — log
iss,sub,appid,jtionly. - Not a substitute for public/anonymous webhook authentication;
signed-secret HMAC patterns remain correct for those. - Short-lived ≠ un-stealable within the token lifetime over TLS;
optional future enhancement is sender-constrained tokens via DPoP
(RFC 9449) or mTLS-bound tokens (RFC 8705).
Are you willing to work on this?
Yes. Happy to contribute a PR against packages/cli/src/public-api,
packages/cli/src/modules/sso-oidc, and the Webhook node:
- New
IdpBearerAuthServicethat wrapsOidcServiceand performs
JWT verification + claim mapping (signature,iss,aud,exp,
nbf, audience allow-list, client-ID allow-list). - New
BearerAuthsecurity scheme in
packages/cli/src/public-api/v1/openapi.yml, and registration of
the middleware inpackages/cli/src/public-api/index.tsalongside
the existingApiKeyAuthhandler. - New “IdP OAuth2” option on the Webhook node authentication
dropdown, wired to the same service. - Extension of the existing OIDC SSO settings page with the new
admin toggles and lists. - Unit tests for the middleware (token validation, audience /
app-ID allow-listing, claim mapping) and integration tests
against a mock IdP.
Would appreciate early direction from the n8n Identity team on:
- Preferred configuration model — per-app allow-list vs. pure
audience check vs. both (current proposal: both, with audience
required and app-ID allow-list optional for per-caller scoping). - Preferred identity representation for service principals inside
n8n — a dedicated “service account” user entity, or a project-scoped
principal with noUserrow. - Whether the admin UI should live inside the existing OIDC settings
page or as a separate “API Authentication” tab.
Thanks for reading!