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.
| Szenario | Warum Standard-OAuth scheitert |
|---|---|
| Callcenter-Agent verifiziert einen Kunden | Der Agent kann nicht das Passwort des Kunden eingeben |
| Zahlungsterminal in einem Geschäft | Der 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-Kiosk | Der Rezeptionist initiiert, der Patient genehmigt auf seinem Telefon |
| Überweisungsautorisierung | Das 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| Parameter | Erforderlich | Beschreibung |
|---|---|---|
login_hint | Ja | Identifiziert den Benutzer — E-Mail, Telefonnummer oder Benutzer-ID |
scope | Ja | Angeforderte OAuth-Scopes (muss openid enthalten) |
binding_message | Empfohlen | Menschenlesbare Beschreibung, die dem Benutzer auf seinem Authentifizierungsgerät angezeigt wird |
requested_expiry | Optional | Wie lange die Authentifizierungsanfrage gültig bleiben soll (Sekunden). Standard: 300 |
client_notification_token | Bedingt | Erforderlich 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-secretDer Server antwortet mit denselben Fehlercodes wie der Device-Flow beim Polling:
| Antwort | Bedeutung |
|---|---|
authorization_pending | Benutzer hat noch nicht geantwortet |
slow_down | Client pollt zu schnell; Intervall um 5 Sekunden erhöhen |
expired_token | Die auth_req_id ist abgelaufen |
access_denied | Benutzer 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-secretAm 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
| Dimension | Poll | Ping | Push |
|---|---|---|---|
| Latenz | Höher (Polling-Intervall) | Niedrig (server-initiiert) | Niedrigste (Tokens im Callback) |
| Client-Komplexität | Einfach (Polling-Schleife) | Mittel (Callback-Endpunkt + Token-Abruf) | Mittel (Callback-Endpunkt) |
| Client-Infrastruktur | Keine (nur ausgehend) | Braucht öffentliche Callback-URL | Braucht öffentliche Callback-URL |
| Token-Sicherheit | Tokens durchqueren nie nicht vertrauenswürdige Netzwerke | Tokens sicher vom Client abgerufen | Tokens an Callback gesendet (höhere Exposition) |
| Am besten für | CLI-Tools, einfache Integrationen | Produktions-Webdienste | Echtzeitsysteme |
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
| Praxis | Beispiel |
|---|---|
| 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 halten | Mobile Push-Benachrichtigungen kürzen lange Nachrichten |
| Keine sensiblen Daten einschließen | Keine 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:
| Kanal | Risiko | Gegenmaßnahme |
|---|---|---|
| Push-Benachrichtigung | Kompromittiertes Telefon, Benachrichtigungsabfangung | Biometrische Entsperrung zur Genehmigung verlangen |
| SMS | SIM-Swapping, SS7-Abfangung | Push-Benachrichtigungen wenn möglich verwenden; SMS nur als Fallback |
| E-Mail-Konto-Kompromittierung, Zustellverzögerung | Push-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:
| Dimension | Device-Flow | CIBA |
|---|---|---|
| Wer initiiert | Benutzer (besucht URL) | Server (sendet Benachrichtigung) |
| Benutzercodeingabe | Benutzer tippt Code manuell | Keine Codeeingabe; Benutzer genehmigt nur |
| Vorherige Benutzerregistrierung | Nicht erforderlich | Erforderlich (Server muss wissen, wie der Benutzer erreichbar ist) |
| Anonyme Benutzer | Unterstützt | Nicht unterstützt |
| UX-Latenz | Höher (Benutzer muss URL besuchen, Code eingeben) | Niedriger (Benutzer tippt auf Benachrichtigung) |
| Benachrichtigungsinfrastruktur | Keine | Erfordert Push/SMS/E-Mail-Fähigkeit |
| Offline-Benutzer | Kann 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:
| Einstellung | Standard | Beschreibung |
|---|---|---|
| CIBA aktivieren | false | Haupt-Toggle |
| Benachrichtigungsmodus | POLL | Wie der Client Tokens erhält (poll, ping oder push) |
| Benachrichtigungskanäle | email | Welche Kanäle für Benutzerbenachrichtigungen verwendet werden (push, sms, email) |
| Maximale Anfrage-Lebensdauer | 300 | Maximales requested_expiry in Sekunden |
| Polling-Intervall | 5 | Minimale Sekunden zwischen Token-Endpunkt-Polls (nur Poll-Modus) |
| Callback-URL | — | Backchannel-Benachrichtigungs-Endpunkt des Clients (erforderlich für ping/push) |
API-Endpunkte
| Endpunkt | Methode | Beschreibung |
|---|---|---|
/api/oauth/ciba | POST | Eine Backchannel-Authentifizierungsanfrage initiieren |
/api/auth/token | POST | Token-Endpunkt (unterstützt urn:openid:params:grant-type:ciba Grant-Typ) |
/hosted/ciba/approve | GET | Benutzerorientierte 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
- Device Authorization Flow — Ein weiterer entkoppelter Authentifizierungsflow, vom Benutzer initiiert
- OAuth 2.0 & OIDC — Das Autorisierungsframework, das CIBA erweitert
- Tokens erklärt — JWT-Struktur, ID-Tokens und Zugriffstoken
- DPoP (Proof of Possession) — Sender-eingeschränkte Tokens, kombinierbar mit CIBA