Package Information
Available Nodes
Documentation generating…
Documentation
n8n-nodes-oidc-login
Community-Node-Package für einen OIDC-Login-Flow, der von einem eingehenden Webhook/Web-Formular
ausgelöst wird und dessen Access Token danach in nachfolgenden HTTP-Request-Nodes per eigenem
Credential-Typ genutzt werden kann.
Enthaltene Bausteine
| Datei | Zweck |
|---|---|
credentials/OidcProviderApi.credentials.ts |
Statische Provider-Settings (Client ID/Secret, Authorization-/Token-URL). Wird vom Trigger-Node gelesen. |
credentials/OidcTokenEncryptionKey.credentials.ts |
Gemeinsames Geheimnis zum symmetrischen Ver-/Entschlüsseln des Access Tokens. Wird vom Trigger-Node (verschlüsseln) gelesen. |
nodes/OidcLoginTrigger/OidcLoginTrigger.node.ts |
Webhook-Trigger mit zwei Endpunkten: Login-Start (Redirect zum OIDC-Server bzw. Cookie-basiertes Auto-Login/Refresh) und Callback (Code-Exchange). Gibt Access/Refresh Token nur verschlüsselt aus, id_token bleibt Klartext. |
credentials/OidcBearerApi.credentials.ts |
Credential mit Feldern Encrypted Access Token (Expression) und Decryption Key, wählbar in jedem HTTP Request Node. Entschlüsselt den Token erst innerhalb von authenticate() — der Klartext taucht nie als Item-Daten auf. |
shared/tokenCrypto.ts |
AES-256-GCM Ver-/Entschlüsselung, von Trigger und OidcBearerApi gemeinsam genutzt. |
shared/cookies.ts |
Cookie-Parsing/-Serialisierung (Set-Cookie-Header bauen, Cookie-Header lesen), vom Trigger genutzt. |
Antwortverhalten (Response Mode)
Das Node-Feld "Response Mode" gilt für den Start-Webhook: sowohl für den Auto-Login/Refresh-
Kurzschluss (gültiger Access-/Refresh-Token-Cookie) als auch für den Request, auf den der Callback nach
erfolgreichem Login redirected (siehe "Ablauf", Schritt 4) — der Callback selbst antwortet nie mehr
direkt, siehe unten.
- "Nach letztem Node" (Default): n8n lässt die Verbindung offen, bis der komplette Workflow
durchgelaufen ist, und schickt dann automatisch die Ausgabe der letzten Node im Workflow als
JSON-Antwort zurück. Baut man z. B. einen HTTP-Request-Node (Repos abrufen) + Set-Node
(Formatierung) dahinter, landet exakt deren Output als JSON-Antwort beim aufrufenden Client. - "Sofort": n8n bestätigt jeden eingehenden Request sofort mit einer generischen Antwort, ohne auf
das Ergebnis des Workflows zu warten. Der Workflow läuft im Hintergrund trotzdem vollständig durch.
Unabhängig vom gewählten Response Mode antworten folgende Fälle immer sofort und manuell (der Workflow
läuft dort gar nicht bzw. noch nicht weiter):
- der reine Redirect zum OIDC-Server (HTTP 302, kein gültiger Token-Cookie vorhanden),
- der Redirect (HTTP 302) vom Callback zurück auf den Start-Webhook nach erfolgreichem Token-Austausch,
- Fehlerfälle beim Callback (ungültiger/abgelaufener
state, Token-Austausch fehlgeschlagen — HTTP 400/502).
Warum drei getrennte Credential-Typen?
OidcProviderApiist statisch (Client ID/Secret ändern sich nicht) → normale, fest gespeicherte Credential.OidcTokenEncryptionKeyundOidcBearerApienthalten denselben Geheimwert (Ver- bzw. Entschlüsselung),
sind aber bewusst zwei getrennte Credential-Typen, keine kombinierte Entity: n8n löst beim Laden
einer Credential IMMER alle Felder auf, auch ungenutzte.OidcBearerApienthält ein Expression-Feld
(Encrypted Access Token, z. B.={{ $('OIDC Login Trigger').item.json.encryptedAccessToken }}),
das sich nur aus dem Ausführungskontext eines nachgelagerten Nodes auflösen lässt. Würde der Trigger
dieselbe Credential referenzieren, versuchte n8n dieses Feld auch im Trigger selbst aufzulösen —
zu diesem Zeitpunkt hat der Trigger (der ja gerade erst läuft) noch keine eigenen Ausführungsdaten,
wodurch die Auflösung mitReferenced node doesn't existfehlschlägt. Der Trigger nutzt daher die
separate, expressionsfreieOidcTokenEncryptionKey-Credential.OidcBearerApiist dynamisch pro Endnutzer/Ausführung — n8n löst Expressions in Credential-Feldern
innerhalb des Kontexts der jeweiligen Workflow-Ausführung auf. Damit bekommt jeder Website-Besucher
in seiner eigenen Ausführung automatisch seinen eigenen, frisch erhaltenen Token — ohne dass Tokens
zwischen Nutzern/Ausführungen vermischt werden.- Damit ihr den Geheimwert trotzdem nicht doppelt pflegen müsst: Beide Credentials (
Encryption KeybeiOidcTokenEncryptionKey,Decryption KeybeiOidcBearerApi) auf dieselbe Expression setzen, z. B.={{$env.OIDC_TOKEN_KEY}}.
Ablauf
Endnutzer ruft
https://<n8n>/webhook/oidc-loginauf (z. B. Link/Redirect aus einem Formular).OidcLoginTriggerprüft zuerst zwei verschlüsselte Cookies aus einem vorherigen Login:- Gültiger
oidc_access_token-Cookie vorhanden → kompletter OIDC-Roundtrip wird übersprungen,
der Workflow läuft sofort mit diesem Token weiter (Schritt 5). - Kein gültiger Access-Token-Cookie, aber ein gültiger
oidc_refresh_token-Cookie → es wird
versucht, pergrant_type=refresh_tokeneinen neuen Access Token zu holen. Klappt das, laufen
beide Cookies neu gesetzt weiter (Schritt 4/5); schlägt der Refresh fehl (z. B. widerrufen/abgelaufen),
fällt der Trigger automatisch auf den normalen Login-Redirect zurück. - Keines von beidem →
OidcLoginTriggergeneriertstate+ PKCEcode_verifier/code_challenge,
merkt sich beides verschlüsselt in einem kurzlebigen<nodeId>_oidc_pending_login-Cookie (10 Min. TTL) und
leitet (HTTP 302) zurauthorizationUrldes OIDC-Servers weiter.
Alle drei Cookie-Namen sind mit der Node-ID prefixt (
<nodeId>_oidc_pending_login,<nodeId>_oidc_access_token,<nodeId>_oidc_refresh_token), damit mehrereOidcLoginTrigger-Instanzen
auf demselben n8n-Host sich nicht gegenseitig die Cookies überschreiben oder auslesen.- Gültiger
Nutzer meldet sich beim Auth-Server an. Dieser leitet zurück auf
https://<n8n>/webhook/oidc-login/callback?code=...&state=....OidcLoginTriggerliest dasoidc_pending_login-Cookie, verifiziertstate, tauschtcodegegen
Access Token (POSTantokenUrl, inkl.code_verifier) und setzt (wie beim Refresh-Fall) zwei neue
Cookies:oidc_access_token, Lifetime =expires_indes Providers.oidc_refresh_token(falls vorhanden), Lifetime = konfigurierbares Feld "Refresh Token Cookie
Lifetime (Days)" am Node (Default 30 Tage).
Beide Cookie-Inhalte sind AES-256-GCM-verschlüsselt mit dem
Encryption Keyaus derOidcTokenEncryptionKey-Credential.Statt direkt zu antworten, redirected
OidcLoginTriggeranschließend (HTTP 302) auf die
Login-Start-URL (.../oidc-login, ohne Query-String) — der frisch gesetzteoidc_access_token-Cookie greift dort sofort über den Kurzschluss-Pfad aus Schritt 2 ("gültiger
Access-Token-Cookie vorhanden"). So verschwindencode/stateaus der sichtbaren Adresszeile, ohne
dass sie dafür zusätzlich zwischengespeichert werden müssen. Trade-off: Der Workflow-Output eines
frischen Logins hat dadurch dieselbe schlankere Form wie bei einem wiederkehrenden Besucher (siehe
Schritt 5) —id_token/expires_in/etc. aus der Token-Response werden nicht mehr an den Workflow
weitergereicht.Der Workflow-Output enthält nur
encryptedAccessToken(verschlüsselt) — bzw. bei einem erfolgreichen
Refresh (Schritt 2, zweiter Fall) zusätzlichencryptedRefreshTokensowieid_token/expires_in/…
im Klartext, da dieser Zweig direkt antwortet statt zu redirecten. Nachfolgende Nodes greifen auf den
Token via$json.encryptedAccessTokenzu; den Klartext liefert erst dasOidcBearerApi-Credential,
und zwar nur innerhalb des jeweiligen HTTP-Requests selbst.
Einrichtung mit Gitea als OIDC-Server
Gitea selbst als Auth-Server nutzt feste, nicht per Discovery konfigurierbare Endpunkte:
- Authorization:
https://<gitea>/login/oauth/authorize - Token:
https://<gitea>/login/oauth/access_token - Userinfo (optional, für Profildaten):
https://<gitea>/login/oauth/userinfo
Schritte in Gitea:
- Als der Nutzer, unter dem die App laufen soll (oder als Admin unter Site Administration →
Applications für eine instanzweite OAuth2-App): Settings → Applications → "Create a new OAuth2 Application". - Application Name vergeben, als Redirect URI exakt die Callback-URL des
OidcLoginTrigger
eintragen (z. B.https://<n8n>/webhook/oidc-login/callback) — muss zeichengenau übereinstimmen,
sonst meldet Gitearedirect_uri_mismatch. - Gitea zeigt Client ID und Client Secret an (Secret nur einmal sichtbar!) → in die
OIDC Provider-Credential in n8n eintragen. - Scope:
openid profile emailfunktioniert bei Gitea für den OIDC-Login. Für Zugriff auf die
Gitea-API selbst (z. B. Repos lesen) ggf. zusätzlich Gitea-spezifische Scopes wieread:repository
ergänzen (Feld "Scope" imOidcLoginTrigger-Node), siehe Gitea-Doku zu "granular scopes". - Optional: ein nachgeschalteter HTTP-Request-Node auf
https://<gitea>/login/oauth/userinfo(GET,
Credential =OIDC Bearer Token) liefert die Profildaten des eingeloggten Gitea-Nutzers — guter Test,
ob der Flow funktioniert.
Einrichtung (allgemein)
npm install
npm run build
npm link
# im n8n Custom-Extensions-Ordner:
npm link n8n-nodes-oidc-login
n8n neu starten. Danach:
- Credential "OIDC Provider" anlegen: Authorization URL, Token URL, Client ID, (optional) Client Secret
eures OIDC-Servers eintragen. - Credential "OIDC Token Encryption Key" anlegen: ein zufälliges, langes Geheimnis eintragen —
idealerweise als Expression={{$env.OIDC_TOKEN_KEY}}, damit dieselbe Umgebungsvariable später auch
imOidcBearerApi-Credential referenziert werden kann (siehe Schritt 5). - Node "OIDC Login Trigger" in den Workflow ziehen, beide Credentials auswählen,
Pathsetzen
(z. B.oidc-login). n8n zeigt dir automatisch zwei Webhook-URLs an (Start +.../callback). - Beim OIDC-Provider den Callback-Webhook (
.../oidc-login/callback) als Redirect URI des Clients
registrieren. - Credential "OIDC Bearer Token" anlegen:
- "Encrypted Access Token" auf Expression umschalten und
={{ $json.encryptedAccessToken }}
eintragen (oder={{ $('OIDC Login Trigger').item.json.encryptedAccessToken }}, falls dazwischen
weitere Nodes liegen). - "Decryption Key" auf denselben Wert wie das
OIDC Token Encryption Key-Credential setzen, also
ebenfalls={{$env.OIDC_TOKEN_KEY}}.
- "Encrypted Access Token" auf Expression umschalten und
- Nachfolgenden HTTP Request Node hinzufügen → Authentication → "Predefined Credential Type" →
"OIDC Bearer Token" auswählen. DerAuthorization: Bearer <token>-Header wird automatisch gesetzt —
der entschlüsselte Token existiert nur kurzzeitig innerhalb dieses Requests, nie als sichtbare
Item-Daten.
Wichtige Einschränkungen / Hinweise
- Ein frisch ausgehandelter Token gilt nur für die Ausführung, in der er erzeugt wurde (jeder
Endnutzer meldet sich selbst an, keine Vermischung zwischen Nutzern). Wiederkehrende Besuche
innerhalb der Cookie-Lifetime lösen aber keinen neuen vollständigen Login-Roundtrip aus, sondern
nutzen Access- bzw. Refresh-Token-Cookie (siehe "Ablauf"). - State-/PKCE-Zwischenspeicherung erfolgt über ein kurzlebiges, verschlüsseltes Cookie
(<nodeId>_oidc_pending_login, 10 Min. TTL) statt Workflow-Static-Data — kein serverseitiger
Cleanup nötig, der Browser verwirft das Cookie selbst nach Ablauf. - Sicherheit: PKCE (S256) wird immer verwendet; Client Secret ist optional (für "public" Clients).
Stellt sicher, dass die n8n-Instanz per HTTPS erreichbar ist, da sensible Tokens durchlaufen (alle
gesetzten Cookies sindHttpOnly/Secure). DerEncryption Key/Decryption Keysollte ein langes,
zufälliges Geheimnis sein — wer ihn kennt, kann die verschlüsselten Cookies/Item-Felder entschlüsseln. - Der HTTP Request Node muss in derselben Workflow-Ausführung wie der Login-Callback bzw. das
Auto-Login/Refresh laufen (direkt oder indirekt nachgeschaltet) — die Credential kann keinen Token
aus einer anderen, bereits abgeschlossenen Ausführung "nachladen".