Skip to Content

CIBA (Client Initiated Backchannel Authentication)

Das Problem: Von jemandem anderem initiierte Authentifizierung

Traditionelle OAuth 2.0-Flows gehen davon aus, dass ein einzelner Benutzer mit einem einzelnen Gerät interagiert: Der Benutzer öffnet einen Browser, gibt Anmeldedaten ein und erhält Tokens — alles auf demselben Gerät, in derselben Sitzung. Dieses Modell funktioniert für Web-Apps und mobile Apps, bricht aber in Szenarien zusammen, in denen die Person, die die Authentifizierung anfordert, nicht dieselbe Person ist, die sich authentifiziert.

SzenarioWarum Standard-OAuth scheitert
Callcenter-Agent verifiziert einen KundenDer Agent kann nicht das Passwort des Kunden eingeben
Zahlungsterminal in einem GeschäftDer Kassierer initiiert, der Kunde genehmigt auf seinem Telefon
Smart-Speaker-Kauf„Alexa, kauf mehr Kaffee” — der Lautsprecher hat keinen Bildschirm für die Anmeldung
Gesundheitswesen-Check-in-KioskDer Rezeptionist initiiert, der Patient genehmigt auf seinem Telefon
ÜberweisungsautorisierungDas Banksystem initiiert, der Kontoinhaber genehmigt aus der Ferne

In all diesen Fällen initiiert eine Partei die Authentifizierungsanfrage und eine andere Partei — der tatsächliche Benutzer — muss sie auf einem separaten Gerät genehmigen. Der Autorisierungsserver muss eine Authentifizierungsanfrage an den Benutzer pushen, anstatt zu warten, bis der Benutzer eine URL besucht.

Was CIBA ist

CIBA (Client Initiated Backchannel Authentication) ist eine OpenID Connect-Erweiterung, die in der CIBA Core Specification  definiert ist. Sie ermöglicht es einer Client-Anwendung, einen Authentifizierungsflow für einen bekannten Benutzer zu initiieren, bei dem sich der Benutzer auf einem separaten Authentifizierungsgerät (typischerweise seinem Telefon) über eine Push-Benachrichtigung, SMS oder E-Mail authentifiziert.

Der wesentliche Unterschied zu anderen OAuth-Flows:

  • Authorization Code + PKCE: Der Benutzer steuert den Flow von Anfang bis Ende auf demselben Gerät.
  • Device Flow: Client zeigt einen Code an, Benutzer besucht eine URL und gibt ihn ein. Der Benutzer initiiert die sekundäre Interaktion.
  • CIBA: Client initiiert, Server pusht eine Benachrichtigung an den Benutzer. Der Benutzer reagiert nur.

CIBA entkoppelt das Verbrauchsgerät (wo der Dienst läuft) vom Authentifizierungsgerät (wo der Benutzer seine Identität beweist).

Funktionsweise von CIBA: Schritt für Schritt

Schritt 1: Client sendet eine Backchannel-Authentifizierungsanfrage

Der Client sendet eine POST-Anfrage an den CIBA-Endpunkt mit einem login_hint, der den Benutzer identifiziert, und einer binding_message, die die Aktion beschreibt:

POST /api/oauth/ciba HTTP/1.1 Host: auth.example.com Content-Type: application/x-www-form-urlencoded Authorization: Bearer <client_access_token> [email protected] &scope=openid profile &binding_message=Kontoüberprüfung für Agent Sarah autorisieren (Ref: TX-9821) &requested_expiry=120 &client_notification_token=notification-callback-token-xyz
ParameterErforderlichBeschreibung
login_hintJaIdentifiziert den Benutzer — E-Mail, Telefonnummer oder Benutzer-ID
scopeJaAngeforderte OAuth-Scopes (muss openid enthalten)
binding_messageEmpfohlenMenschenlesbare Beschreibung, die dem Benutzer auf seinem Authentifizierungsgerät angezeigt wird
requested_expiryOptionalWie lange die Authentifizierungsanfrage gültig bleiben soll (Sekunden). Standard: 300
client_notification_tokenBedingtErforderlich für Ping- und Push-Modi; das Token, das Auris im Callback zurücksendet

Schritt 2: Server gibt eine Authentifizierungsanfrage-ID zurück

Wenn der login_hint genau einem Benutzer entspricht und der Client zur Verwendung von CIBA berechtigt ist, antwortet der Server:

{ "auth_req_id": "ciba_req_1a2b3c4d5e6f7g8h", "expires_in": 120, "interval": 5 }

Die auth_req_id ist der Handle, den der Client verwendet, um den Status der Authentifizierungsanfrage zu prüfen.

Schritt 3: Server benachrichtigt den Benutzer

Auris sendet eine Benachrichtigung an das Authentifizierungsgerät des Benutzers über einen der konfigurierten Kanäle:

  • Push-Benachrichtigung: Natives Mobile-Push (erfordert, dass der Benutzer die Authenticator-App installiert hat)
  • SMS: Textnachricht mit einem Link zur Genehmigungsseite
  • E-Mail: E-Mail mit einem Link zur Genehmigungsseite

Die Benachrichtigung enthält die binding_message, damit der Benutzer genau weiß, was er genehmigt.

Schritt 4: Benutzer genehmigt oder lehnt ab

Der Benutzer sieht die Binding-Message und den Namen der anfragenden Anwendung auf seinem Authentifizierungsgerät. Er kann:

  • Genehmigen: Der Autorisierungsserver markiert die CIBA-Anfrage als genehmigt und (falls erforderlich) schließt der Benutzer MFA ab
  • Ablehnen: Der Autorisierungsserver markiert die Anfrage als abgelehnt; der Client erhält beim nächsten Poll access_denied

Schritt 5: Client erhält Tokens

Wie der Client die Tokens erhält, hängt vom konfigurierten Benachrichtigungsmodus ab (siehe nächsten Abschnitt).

Die drei Benachrichtigungsmodi

CIBA definiert drei Wege, auf denen der Client Tokens nach der Genehmigung des Benutzers erhält. Jeder macht einen anderen Kompromiss zwischen Einfachheit, Latenz und Infrastrukturanforderungen.

Poll-Modus

Der einfachste Modus. Der Client pollt den Token-Endpunkt im konfigurierten interval, genau wie der Device-Flow:

POST /api/auth/token HTTP/1.1 Host: auth.example.com Content-Type: application/x-www-form-urlencoded grant_type=urn:openid:params:grant-type:ciba &auth_req_id=ciba_req_1a2b3c4d5e6f7g8h &client_id=call-center-app &client_secret=client-secret

Der Server antwortet mit denselben Fehlercodes wie der Device-Flow beim Polling:

AntwortBedeutung
authorization_pendingBenutzer hat noch nicht geantwortet
slow_downClient pollt zu schnell; Intervall um 5 Sekunden erhöhen
expired_tokenDie auth_req_id ist abgelaufen
access_deniedBenutzer hat die Anfrage abgelehnt
Erfolg (200)Tokens zurückgegeben

Am besten für: Einfache Integrationen, bei denen eine 5-Sekunden-Latenz akzeptabel ist.

Ping-Modus

Im Ping-Modus sendet der Autorisierungsserver ein HTTP-POST an die registrierte Callback-URL des Clients, wenn der Benutzer antwortet. Der Callback-Body enthält nur die auth_req_id — der Client muss dann die Tokens vom Token-Endpunkt abrufen.

// Server pingt den Callback des Clients POST /ciba-callback HTTP/1.1 Host: client.example.com Content-Type: application/json Authorization: Bearer <client_notification_token> { "auth_req_id": "ciba_req_1a2b3c4d5e6f7g8h" }

Der Client ruft dann Tokens normal ab:

POST /api/auth/token HTTP/1.1 Host: auth.example.com Content-Type: application/x-www-form-urlencoded grant_type=urn:openid:params:grant-type:ciba &auth_req_id=ciba_req_1a2b3c4d5e6f7g8h &client_id=call-center-app &client_secret=client-secret

Am besten für: Produktionssysteme, bei denen der Client eine öffentlich erreichbare Callback-URL hat und niedrigere Latenz als der Poll-Modus benötigt.

Push-Modus

Im Push-Modus pusht der Autorisierungsserver die tatsächlichen Tokens direkt an die Callback-URL des Clients. Der Client ruft nie den Token-Endpunkt auf.

// Server pusht Tokens an den Callback des Clients POST /ciba-callback HTTP/1.1 Host: client.example.com Content-Type: application/json Authorization: Bearer <client_notification_token> { "auth_req_id": "ciba_req_1a2b3c4d5e6f7g8h", "access_token": "eyJhbGciOiJSUzI1NiJ9...", "token_type": "Bearer", "expires_in": 3600, "id_token": "eyJhbGciOiJSUzI1NiJ9..." }

Am besten für: Niedrigste Latenz. Die Tokens reisen jedoch über das Netzwerk zum Callback des Clients, was die Angriffsfläche erhöht.

Modus-Vergleich

DimensionPollPingPush
LatenzHöher (Polling-Intervall)Niedrig (server-initiiert)Niedrigste (Tokens im Callback)
Client-KomplexitätEinfach (Polling-Schleife)Mittel (Callback-Endpunkt + Token-Abruf)Mittel (Callback-Endpunkt)
Client-InfrastrukturKeine (nur ausgehend)Braucht öffentliche Callback-URLBraucht öffentliche Callback-URL
Token-SicherheitTokens durchqueren nie nicht vertrauenswürdige NetzwerkeTokens sicher vom Client abgerufenTokens an Callback gesendet (höhere Exposition)
Am besten fürCLI-Tools, einfache IntegrationenProduktions-WebdiensteEchtzeitsysteme

Auris unterstützt alle drei Modi. Poll-Modus ist der Standard für neue Anwendungen. Um den Ping- oder Push-Modus zu verwenden, registriere einen backchannel_client_notification_endpoint in den Anwendungseinstellungen und füge bei jeder CIBA-Anfrage ein client_notification_token hinzu.

Die Binding-Message

Die binding_message ist wohl die wichtigste Sicherheitsfunktion von CIBA. Es ist ein kurzer, menschenlesbarer String, der dem Benutzer auf seinem Authentifizierungsgerät angezeigt wird und genau beschreibt, was er genehmigt.

Warum sie wichtig ist

Ohne eine Binding-Message ist CIBA anfällig für Confused-Deputy-Angriffe: Ein Angreifer initiiert eine CIBA-Anfrage für einen Opfer-Benutzer, und das Opfer sieht eine generische „Anmeldung genehmigen?”-Aufforderung ohne Kontext. Das Opfer genehmigt, weil es denkt, es sei sein eigener Anmeldeversuch, und der Angreifer erhält an das Benutzerkonto gebundene Tokens.

Mit einer Binding-Message sieht das Opfer:

„Überweisung von 5.000 € auf Konto mit Endung 7892 autorisieren (Ref: WT-2024-0918)”

Wenn das Opfer keine Überweisung initiiert hat, weiß es, dass es die Anfrage ablehnen soll.

Best Practices

PraxisBeispiel
Die zu autorisierende Aktion einschließen„Zahlung von EUR 49,99 autorisieren”
Eine Referenznummer einschließen„(Ref: TX-9821)“
Die anfragende Partei einschließen„Agent Sarah bei ACME Bank”
Unter 200 Zeichen haltenMobile Push-Benachrichtigungen kürzen lange Nachrichten
Keine sensiblen Daten einschließenKeine vollständigen Kontonummern oder Ausweisdaten in die Nachricht

Die binding_message wird auf dem Gerät des Benutzers angezeigt, was möglicherweise eine Push-Benachrichtigung auf dem Sperrbildschirm ist. Füge niemals Passwörter, vollständige Kreditkartennummern oder andere sensible Informationen in die Binding-Message ein.

Sicherheitsanalyse

Lebensdauer der Authentifizierungsanfrage

CIBA-Anfragen haben eine kurze Lebensdauer (Standard 300 Sekunden, konfigurierbar über requested_expiry bis zu einem vom Server vorgegebenen Maximum). Nach dem Ablauf ist die auth_req_id ungültig und der Client muss einen neuen Flow starten.

Login-Hint-Auflösung

Der login_hint muss genau einem Benutzer entsprechen. Wenn der Hint mehrdeutig ist (z. B. ein häufiger Name, der mehreren Benutzern entspricht), lehnt der Server die Anfrage mit unknown_user_id ab. Dies verhindert Angriffe, bei denen ein Angreifer einen bestimmten Benutzer durch Angabe eines vagen Hints anvisiert.

Sicherheit des Benachrichtigungskanals

Die Sicherheit von CIBA hängt von der Sicherheit des Benachrichtigungskanals ab:

KanalRisikoGegenmaßnahme
Push-BenachrichtigungKompromittiertes Telefon, BenachrichtigungsabfangungBiometrische Entsperrung zur Genehmigung verlangen
SMSSIM-Swapping, SS7-AbfangungPush-Benachrichtigungen wenn möglich verwenden; SMS nur als Fallback
E-MailE-Mail-Konto-Kompromittierung, ZustellverzögerungPush-Benachrichtigungen wenn möglich verwenden; E-Mail nur als Fallback

CIBA + DPoP

CIBA kann mit DPoP kombiniert werden, um sender-eingeschränkte Tokens zu erzeugen. Der Client enthält einen DPoP-Proof beim Polling/Abrufen von Tokens, und das resultierende Zugriffstoken ist an das Schlüsselpaar des Clients gebunden. Dies bietet eine zusätzliche Schutzschicht, wenn die Tokens während der Zustellung abgefangen werden (besonders relevant im Push-Modus).

Vergleich: CIBA vs Device-Flow

Sowohl CIBA als auch Device-Flow authentifizieren einen Benutzer, der nicht direkt mit dem Client-Gerät interagiert. Der grundlegende Unterschied ist, wer die Sekundärgeräte-Interaktion initiiert:

DimensionDevice-FlowCIBA
Wer initiiertBenutzer (besucht URL)Server (sendet Benachrichtigung)
BenutzercodeingabeBenutzer tippt Code manuellKeine Codeeingabe; Benutzer genehmigt nur
Vorherige BenutzerregistrierungNicht erforderlichErforderlich (Server muss wissen, wie der Benutzer erreichbar ist)
Anonyme BenutzerUnterstütztNicht unterstützt
UX-LatenzHöher (Benutzer muss URL besuchen, Code eingeben)Niedriger (Benutzer tippt auf Benachrichtigung)
BenachrichtigungsinfrastrukturKeineErfordert Push/SMS/E-Mail-Fähigkeit
Offline-BenutzerKann sich später authentifizieren (innerhalb der Code-Lebensdauer)Kann keine Benachrichtigung empfangen, wenn offline

Auris-Implementierungsdetails

Prisma-Modell

model CibaAuthRequest { id String @id @default(cuid()) tenantId String applicationId String authReqId String @unique loginHint String userId String? scope String? bindingMessage String? status CibaAuthStatus @default(PENDING) notificationMode CibaNotificationMode @default(POLL) clientNotificationToken String? expiresAt DateTime interval Int @default(5) createdAt DateTime @default(now()) } enum CibaAuthStatus { PENDING APPROVED DENIED EXPIRED } enum CibaNotificationMode { POLL PING PUSH }

Konfiguration

CIBA wird pro Anwendung in der Auris-Konsole unter Anwendungen > (Anwendung auswählen) > Einstellungen aktiviert:

EinstellungStandardBeschreibung
CIBA aktivierenfalseHaupt-Toggle
BenachrichtigungsmodusPOLLWie der Client Tokens erhält (poll, ping oder push)
BenachrichtigungskanäleemailWelche Kanäle für Benutzerbenachrichtigungen verwendet werden (push, sms, email)
Maximale Anfrage-Lebensdauer300Maximales requested_expiry in Sekunden
Polling-Intervall5Minimale Sekunden zwischen Token-Endpunkt-Polls (nur Poll-Modus)
Callback-URL—Backchannel-Benachrichtigungs-Endpunkt des Clients (erforderlich für ping/push)

API-Endpunkte

EndpunktMethodeBeschreibung
/api/oauth/cibaPOSTEine Backchannel-Authentifizierungsanfrage initiieren
/api/auth/tokenPOSTToken-Endpunkt (unterstützt urn:openid:params:grant-type:ciba Grant-Typ)
/hosted/ciba/approveGETBenutzerorientierte Genehmigungsseite (verlinkt aus Benachrichtigung)

Codebeispiel: Callcenter-Agent-Flow

async function verifyCustomerIdentity( customerEmail: string, agentName: string, referenceNumber: string ) { // Schritt 1: CIBA-Anfrage initiieren const cibaResponse = await fetch('https://auth.example.com/api/oauth/ciba', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Authorization: `Bearer ${agentAccessToken}`, }, body: new URLSearchParams({ login_hint: customerEmail, scope: 'openid profile', binding_message: `Identitätsüberprüfung durch ${agentName} (Ref: ${referenceNumber})`, requested_expiry: '120', }), }) const { auth_req_id, interval, expires_in } = await cibaResponse.json() console.log(`Verifizierung an ${customerEmail} gesendet. Warte auf Genehmigung...`) // Schritt 2: Auf Abschluss pollen (Poll-Modus) let pollInterval = interval * 1000 const deadline = Date.now() + expires_in * 1000 while (Date.now() < deadline) { await new Promise(resolve => setTimeout(resolve, pollInterval)) const tokenResponse = await fetch('https://auth.example.com/api/auth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'urn:openid:params:grant-type:ciba', auth_req_id, client_id: 'call-center-app', client_secret: 'client-secret', }), }) if (tokenResponse.ok) { const { id_token } = await tokenResponse.json() console.log('Kundenidentität verifiziert.') return id_token // Enthält verifizierte Benutzer-Claims } const error = await tokenResponse.json() if (error.error === 'slow_down') { pollInterval += 5000 continue } if (error.error === 'authorization_pending') continue if (error.error === 'access_denied') { throw new Error('Kunde hat die Verifizierungsanfrage abgelehnt.') } throw new Error(`Verifizierung fehlgeschlagen: ${error.error_description}`) } throw new Error('Verifizierungsanfrage abgelaufen. Kunde hat nicht rechtzeitig geantwortet.') }

Verwandte Konzepte