Skip to Content

Token Exchange

Token Exchange (RFC 8693) ist ein OAuth 2.0-Erweiterungsgrant, der es einem privilegierten Dienst erlaubt, ein vorhandenes Token gegen ein neues Token einzutauschen, das entweder:

  • Die Identität eines anderen Benutzers annimmt (Impersonation): Das sub im neuen Token ist der Zielbenutzer, nicht der anfragende Dienst.
  • Im Namen eines anderen Dienstes handelt (Delegation): Das sub im neuen Token ist dasselbe, aber der act-Claim zeichnet den delegierenden Dienst auf.
ImpersonationDelegation
subÄndert sich zum ZielbenutzerBleibt beim ursprünglichen Subjekt
actOriginal-Actor (Admin, der imitiert)Delegierender Dienst
Typischer AnwendungsfallAdmin übernimmt Benutzersitzung für SupportFrontend-Dienst handelt im Namen des Benutzers gegenüber Backend
Berechtigungimpersonate:usersdelegate:tokens

Impersonation-Token-Struktur

{ "sub": "target-user-id", "email": "[email protected]", "roles": ["member"], "act": { "sub": "admin-user-id", "email": "[email protected]" }, "iat": 1700000000, "exp": 1700003600 }

Das act-Claim zeigt immer die Person oder den Dienst, der tatsächlich handelt — wesentlich für Audit-Logs.

Delegations-Token-Struktur

{ "sub": "original-user-id", "aud": "backend-service", "act": { "sub": "frontend-service-client-id" }, "scope": "read:invoices", "iat": 1700000000, "exp": 1700003600 }

Einrichten

  1. Öffne die Auris Console → Applications → deine Anwendung.
  2. Navigiere zu Advanced → Token Exchange und aktiviere es.
  3. Konfiguriere, welche Exchange-Typen erlaubt sind: Impersonation, Delegation oder beide.
  4. Weise der aufrufenden Client-Anwendung die erforderlichen Berechtigungen zu:
    • Für Impersonation: impersonate:users
    • Für Delegation: delegate:tokens

Token Exchange erfordert einen vertraulichen Client (confidential client) mit einem client_secret. Öffentliche Clients (z.B. Single-Page-Apps ohne Backend) können keine Token-Exchanges durchführen.


Verwendung

import { AurisManagementClient } from '@auris/js' const mgmt = new AurisManagementClient({ domain: process.env.AURIS_DOMAIN, clientId: process.env.AURIS_CLIENT_ID, clientSecret: process.env.AURIS_CLIENT_SECRET, }) // Impersonation — handeln als target-user const impersonatedToken = await mgmt.auth.exchangeToken({ subjectToken: existingAccessToken, subjectTokenType: 'urn:ietf:params:oauth:token-type:access_token', requestedTokenType: 'urn:ietf:params:oauth:token-type:access_token', requestedSubject: 'user-id-to-impersonate', audience: 'https://api.yourdomain.com', scope: 'read:invoices view:profile', }) console.log(impersonatedToken.access_token) // Token mit sub = Zielbenutzer // Delegation — im Auftrag des ursprünglichen Benutzers gegenüber einem Backend handeln const delegatedToken = await mgmt.auth.exchangeToken({ subjectToken: userAccessToken, subjectTokenType: 'urn:ietf:params:oauth:token-type:access_token', requestedTokenType: 'urn:ietf:params:oauth:token-type:access_token', audience: 'backend-service', scope: 'read:invoices', // Scope kann nur eingeschränkt werden })

Anfrage-Parameter

ParameterPflichtBeschreibung
grant_type✅Muss urn:ietf:params:oauth:grant-type:token-exchange sein
client_id✅Client-ID der anfragenden Anwendung
client_secret✅Client-Secret (vertrauliche Clients erforderlich)
subject_token✅Das einzutauschende Token
subject_token_type✅Typ des subject_token (normalerweise urn:ietf:params:oauth:token-type:access_token)
requested_token_typeTyp des angeforderten Tokens (Standard: access_token)
requested_subjectBei Impersonation: Benutzer-ID des Ziel-Subjekts
audienceBeabsichtigte Ziel-Audience des neuen Tokens
scopeAngeforderter Scope; kann nur eingeschränkt, nicht erweitert werden

Verschachtelte Delegationsketten

Der act-Claim kann verschachtelt werden, um mehrstufige Delegation aufzuzeichnen:

{ "sub": "user-123", "act": { "sub": "api-gateway-client-id", "act": { "sub": "frontend-service-client-id" } } }

Dies zeigt: frontend-service delegierte an api-gateway, der nun im Namen von user-123 handelt. Jede Ebene ist im Token vollständig nachvollziehbar.


Ausgetauschte Tokens validieren

Im Backend solltest du ausgetauschte Tokens identifizieren und entsprechend handeln:

import { verifyToken } from '@auris/node' const payload = await verifyToken(accessToken, { domain: process.env.AURIS_DOMAIN!, audience: process.env.AURIS_AUDIENCE!, }) if (payload.act) { // Dieses Token ist das Ergebnis eines Token Exchange const effectiveSubject = payload.sub // Wer handelt const originalActor = payload.act.sub // Wer hat initiiert // Für Audit-Logs immer beide protokollieren logger.info('Token Exchange erkannt', { effectiveSubject, originalActor, action: req.method + ' ' + req.path, }) // Hochriskante destruktive Operationen für imitierte Tokens blockieren if (isDestructiveOperation(req) && effectiveSubject !== originalActor) { return res.status(403).json({ error: 'Destruktive Operationen durch Impersonation nicht erlaubt' }) } }

Sicherheitshinweise

  • Scope kann nur eingeschränkt werden: Ein ausgetauschtes Token darf nie einen breiteren Scope haben als das Ursprungs-Token.
  • Vertraulicher Client erforderlich: Öffentliche Clients können keinen Token Exchange durchführen.
  • 1-Stunden-Lebensdauer: Ausgetauschte Tokens laufen standardmäßig nach 1 Stunde ab, unabhängig von der Ursprungs-Token-Lebensdauer.
  • Vollständiges Audit-Logging: Alle Token-Exchanges werden im Auris Audit-Log protokolliert — wer hat für wen getauscht, wann und für welchen Scope.
  • Impersonation-Schutz: Verwende act-Claim-Prüfungen in deiner API, um imitierte Tokens von regulären Tokens zu unterscheiden.

API-Referenz

POST/api/auth/token

Token-Exchange-Grant-Endpunkt. Akzeptiert grant_type=urn:ietf:params:oauth:grant-type:token-exchange mit den oben genannten Parametern.

GET/api/oauth/token-exchangesRequires: view:token_exchanges

Auflisten aller Token-Exchanges, die im Tenant durchgeführt wurden. Gibt paginierte Exchange-Datensätze mit Actor, Subject, Audience, Scope und Zeitstempel zurück.


Berechtigungen

BerechtigungBeschreibung
impersonate:usersErlaubt dem Dienst, als ein anderer Benutzer zu imitieren (requested_subject)
delegate:tokensErlaubt dem Dienst, Delegation-Token-Exchanges durchzuführen
view:token_exchangesErlaubt das Auflisten von Token-Exchange-Protokollen in der Management API
manage:applicationsErforderlich, um Token Exchange in der Anwendungskonfiguration zu aktivieren/deaktivieren

Verwandte Anleitungen