Skip to Content

Benutzerdefinierte Actions schreiben

Actions sind benutzerdefinierte JavaScript-Funktionen, die an bestimmten Punkten in der Auris-Authentifizierungspipeline ausgeführt werden. Sie ermöglichen es dir, das Plattformverhalten zu erweitern, ohne Auris selbst zu forken oder zu modifizieren — füge benutzerdefinierte Claims zu Tokens hinzu, blockiere Logins basierend auf externen Daten, rufe Webhooks auf, setze Geschäftsregeln durch oder integriere Drittanbieterdienste.

Wann Actions vs. andere Erweiterungspunkte verwenden

MechanismusAm besten für
ActionsLogik, die synchron während des Auth-Flows laufen muss (Login blockieren, Claims hinzufügen, Benutzer-Metadaten ändern)
Custom ClaimsStatische oder attributbasierte Token-Anreicherung, die keine externen Aufrufe oder bedingte Logik erfordert
WebhooksAsynchrone Benachrichtigungen nach dem Auftreten von Ereignissen (Audit-Logging, Analytics, Slack-Alerts)

Wenn dein Anwendungsfall einen externen API-Aufruf erfordert, der erfolgreich sein muss, bevor der Login abgeschlossen ist, verwende eine Action. Wenn du ein System nur im Nachhinein benachrichtigen musst, verwende einen Webhook.


Die Sandbox-Umgebung

Actions werden in einer eingeschränkten JavaScript-Sandbox ausgeführt. Die Sandbox bietet:

Verfügbare APIs

APIHinweise
fetch()HTTP-Anfragen an externe Dienste stellen. Vollständige Fetch-API.
JSONJSON.parse() und JSON.stringify()
DateDatumskonstruktion und -manipulation
MathMathematische Operationen
console.log()Ausgabe wird erfasst und in Action-Logs sichtbar
String, Number, Boolean, Array, ObjectStandardmäßige eingebaute Typen
Promise, async/awaitAsynchroner Code wird vollständig unterstützt
URL, URLSearchParamsURL-Parsing und -Konstruktion
TextEncoder, TextDecoderText-Encoding-Hilfsmittel
crypto.randomUUID()UUID-Generierung

Blockierte APIs

Folgende sind aus Sicherheitsgründen blockiert:

BlockiertGrund
require(), importKein Modulsystemzugriff
processKein Zugriff auf Umgebungsvariablen oder Prozessinfos
Dynamische Code-AusführungsfunktionenKeine Laufzeit-Code-Generierung
global, globalThisKein Zugriff auf den globalen Bereich
fs, child_processKein Dateisystem- oder Prozess-Spawning

Actions haben ein konfigurierbares Ausführungs-Timeout (Standard: 5 Sekunden, max: 30 Sekunden). Wenn eine Action das Timeout überschreitet, wird sie beendet und das konfigurierte Fehlverhalten greift (Anfrage erlauben oder ablehnen).


Trigger-Typen

Actions feuern an bestimmten Punkten im Authentifizierungsflow. Jeder Trigger erhält ein anderes context-Objekt:

TriggerWann er feuertHäufige Verwendungen
pre-loginBevor Anmeldedaten verifiziert werdenLogins nach E-Mail-Domain blockieren, externe Blocklisten prüfen
post-loginNach erfolgreicher Authentifizierung, vor Token-AusgabeBenutzerdefinierte Claims hinzufügen, mit externen Systemen synchronisieren, bedingtes MFA
pre-signupBevor ein neuer Benutzer erstellt wirdE-Mail-Domain validieren, Einladungsanforderungen prüfen
post-signupNachdem ein neuer Benutzer erstellt wurdeWillkommens-Webhook senden, zu Organisation hinzufügen, Metadaten setzen
post-change-passwordNach einer PasswortänderungExterne Systeme benachrichtigen, gecachte Sitzungen invalidieren
pre-m2m-tokenBevor ein M2M-Token ausgegeben wirdScopes einschränken, Client gegen externe Regeln validieren

Das Context-Objekt

Jede Action erhält ein context-Objekt mit Informationen über die aktuelle Anfrage. Die Form variiert je nach Trigger:

pre-login und post-login

{ user: { id: 'user-123', email: '[email protected]', username: 'alice', firstName: 'Alice', lastName: 'Smith', roles: ['editor', 'viewer'], metadata: { plan: 'pro', company: 'Acme' }, }, request: { ip: '203.0.113.42', userAgent: 'Mozilla/5.0...', geoip: { country: 'IT', city: 'Milan' }, }, application: { id: 'app-456', name: 'Dashboard', type: 'WEB', }, tenant: { id: 'tenant-789', name: 'acme-corp', }, }

pre-m2m-token

{ client: { id: 'client-abc', name: 'Billing Service', type: 'M2M', }, requestedScopes: ['read:users', 'manage:billing'], tenant: { id: 'tenant-789', name: 'acme-corp' }, }

Der ActionResult-Rückgabetyp

Actions geben ein Objekt zurück, das das Ergebnis steuert:

interface ActionResult { allow: boolean // true = fortfahren, false = Anfrage blockieren message?: string // Fehlermeldung für den Benutzer bei allow=false claims?: Record<string, any> // Benutzerdefinierte Claims zum Token hinzufügen (post-login, pre-m2m-token) metadata?: Record<string, any> // Metadaten im Benutzerdatensatz setzen }

Wenn eine Action kein Ergebnis zurückgibt (oder undefined zurückgibt), wird die Anfrage normal fortgesetzt.


Praktische Beispiele

Logins nach E-Mail-Domain blockieren

// Trigger: pre-login // Persönliche E-Mail-Anbieter beim Login blockieren const blockedDomains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com'] const domain = context.user.email.split('@')[1] if (blockedDomains.includes(domain)) { return { allow: false, message: 'Persönliche E-Mail-Adressen sind nicht erlaubt. Bitte verwende deine Firmen-E-Mail.', } } return { allow: true }

Benutzerdefinierte Claims basierend auf Rollen hinzufügen

// Trigger: post-login // Einen 'plan'-Claim und Feature-Flags basierend auf Benutzer-Metadaten hinzufügen const plan = context.user.metadata?.plan || 'free' const featureFlags = { free: { maxProjects: 3, analytics: false, exportEnabled: false }, pro: { maxProjects: 50, analytics: true, exportEnabled: true }, enterprise: { maxProjects: -1, analytics: true, exportEnabled: true }, } return { allow: true, claims: { plan, features: featureFlags[plan] || featureFlags.free, 'https://myapp.com/roles': context.user.roles, }, }

Authentifizierungsereignisse an einen externen Webhook protokollieren

// Trigger: post-login // Webhook-Benachrichtigung für jeden Login senden try { await fetch('https://hooks.example.com/auth-events', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ event: 'user.login', userId: context.user.id, email: context.user.email, ip: context.request.ip, country: context.request.geoip?.country, timestamp: new Date().toISOString(), }), }) } catch (err) { // Nicht kritisch -- protokollieren, aber Login nicht blockieren console.log('Webhook fehlgeschlagen:', err.message) } return { allow: true }

M2M-Scopes basierend auf externer Richtlinie einschränken

// Trigger: pre-m2m-token // Externen Richtlinien-Service prüfen, bevor M2M-Tokens ausgestellt werden const response = await fetch('https://policy.internal/check', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientId: context.client.id, scopes: context.requestedScopes, }), }) if (!response.ok) { return { allow: false, message: 'Token-Anfrage vom Richtlinien-Service abgelehnt.', } } const policy = await response.json() return { allow: true, claims: { scope: policy.allowedScopes.join(' '), 'policy-version': policy.version, }, }

Bedingter MFA-Trigger

// Trigger: post-login // MFA für Admin-Rollen oder Logins aus neuen Ländern verlangen const isAdmin = context.user.roles.includes('admin') const isNewCountry = context.request.geoip?.country !== context.user.metadata?.lastCountry if (isAdmin || isNewCountry) { return { allow: true, metadata: { lastCountry: context.request.geoip?.country, requireMfa: true, }, } } return { allow: true, metadata: { lastCountry: context.request.geoip?.country }, }

Ausführungsreihenfolge

Wenn mehrere Actions für denselben Trigger konfiguriert sind, werden sie in der durch ihr order-Feld definierten Reihenfolge (aufsteigend) ausgeführt. Jede Action erhält denselben ursprünglichen Kontext — die Ausgabe einer Action ändert den Kontext für nachfolgende Actions nicht.

Claims und Metadaten aus allen Actions werden jedoch zusammengeführt. Wenn zwei Actions denselben Claim-Schlüssel setzen, gewinnt die zuletzt in der Reihenfolge stehende Action.

Action-ReihenfolgeAction-NameClaims-Ausgabe
1Plan-Claim hinzufügen{ plan: 'pro' }
2Feature-Flags hinzufügen{ features: { ... } }
3Region-Claim hinzufügen{ region: 'eu' }

Finale Token-Claims: { plan: 'pro', features: { ... }, region: 'eu' }

Wenn eine Action allow: false zurückgibt, wird die gesamte Pipeline angehalten und die Anfrage abgelehnt, unabhängig von nachfolgenden Actions.


Der Blueprint Visual Editor

Für Teams, die einen visuellen Ansatz bevorzugen, bietet Auris einen Blueprint-Editor — einen knotenbasierten visuellen Regel-Builder, inspiriert von Unreal Engines Blueprint-System.

Der Blueprint-Editor stellt Actions als einen Graphen verbundener Knoten dar:

KnotentypFarbeZweck
TriggerOrangeDer Einstiegspunkt — welches Auth-Ereignis die Regel auslöst
ConditionCyanEin Feld gegen einen Wert prüfen (z. B. user.email contains @acme.com)
Logic GateViolettBedingungen mit AND/OR kombinieren
DenyPinkDie Anfrage mit einer Fehlermeldung blockieren
Set ClaimsBlauSchlüssel-Wert-Paare zum Token hinzufügen
Set MetadataSmaragdgrünBenutzer-Metadaten aktualisieren
LogGrünIn Action-Logs schreiben

Der Blueprint-Editor und der Code-Editor sind zwei Ansichten derselben zugrunde liegenden Action. Änderungen in einer werden mit der anderen synchronisiert. Du kannst mit Blueprint für einfache Regeln beginnen und für komplexe Logik zum Code wechseln.

Um auf den Blueprint-Editor zuzugreifen, öffne die Detailseite einer Action in der Console und klicke auf den Blueprint-Reiter.


Actions debuggen

Action-Logs

Jede Action-Ausführung wird protokolliert. Logs können in Console → Actions → [Action-Name] → Logs-Reiter angesehen werden. Jeder Log-Eintrag enthält:

  • Ausführungs-Zeitstempel
  • Trigger-Ereignis
  • Ausführungsdauer (ms)
  • Status (Erfolg, Fehler, Timeout)
  • console.log-Ausgabe
  • Rückgabewert

console.log verwenden

console.log()-Ausgabe wird erfasst und im Action-Log gespeichert:

console.log('Benutzer-Rollen:', JSON.stringify(context.user.roles)) console.log('Anfrage-IP:', context.request.ip) console.log('GeoIP-Daten:', JSON.stringify(context.request.geoip)) // Diese Ausgabe erscheint im Logs-Reiter der Action return { allow: true }

Fehlerbehandlung

Wenn eine Action einen unbehandelten Fehler wirft, hängt das Verhalten von der Fehlermodus-Einstellung der Action ab:

FehlermodusVerhalten
allow (Standard)Die Anfrage wird fortgesetzt. Der Fehler wird protokolliert.
denyDie Anfrage wird mit einer generischen Fehlermeldung blockiert.

Verwende immer try/catch rund um externe API-Aufrufe, um zu verhindern, dass Fehler Logins blockieren:

try { const result = await fetch('https://external-api.example.com/check') // Ergebnis verarbeiten } catch (err) { console.log('Externe API fehlgeschlagen, fortfahren:', err.message) // Login nicht blockieren, weil ein externer Service ausgefallen ist } return { allow: true }

Performance-Tipps

  1. Actions schnell halten — Strebe weniger als 100ms Ausführungszeit an. Jede Millisekunde erhöht die Login-Latenz.
  2. try/catch für externe Aufrufe verwenden — Lass niemals einen nicht-kritischen externen API-Fehler einen Login blockieren.
  3. Sequentielle externe Aufrufe vermeiden — Wenn du mehrere API-Aufrufe benötigst, verwende Promise.all(), um sie parallel auszuführen.
  4. Teure Lookups cachen — Für Daten, die sich selten ändern, erwäge das Caching in Benutzer-Metadaten und periodische Aktualisierung, anstatt bei jedem Login abzufragen.
  5. Angemessene Timeouts setzen — Verwende AbortController mit fetch(), um explizite Timeouts kürzer als das Action-Timeout zu setzen:
const controller = new AbortController() setTimeout(() => controller.abort(), 3000) // 3-Sekunden-Timeout const response = await fetch('https://slow-api.example.com/check', { signal: controller.signal, })

API-Endpunkte

GET/api/actionsRequires: view:actions

Alle Actions für den Tenant auflisten. Unterstützt Filterung nach Trigger-Typ und Status.

POST/api/actionsRequires: manage:actions

Eine neue Action erstellen. Erfordert name, trigger, code und optional order, timeout, status.

GET/api/actions/:idRequires: view:actions

Action-Details abrufen, einschließlich Code, Trigger, Ausführungsanzahl und Fehleranzahl.

PATCH/api/actions/:idRequires: manage:actions

Code, Trigger, Reihenfolge, Timeout oder Status einer Action aktualisieren.

DELETE/api/actions/:idRequires: manage:actions

Eine Action löschen.

GET/api/actions/:id/logsRequires: view:actions

Ausführungslogs für eine bestimmte Action auflisten. Enthält Dauer, Status, Konsolenausgabe und Rückgabewert.


Erforderliche Berechtigungen

OperationBerechtigung
Actions anzeigenview:actions
Actions erstellen, bearbeiten, löschenmanage:actions
Action-Logs anzeigenview:actions

Verwandte Leitfäden