OpenID Connect · OAuth 2.0
Diese Mechanismen stärken die Sicherheit des Basisablaufs. Jeder begegnet einer bestimmten Schwäche: Wir beginnen mit dem Problem, dann die Lösung.
Der rote Faden
Der Basisablauf sendet Informationen über den Browser, wo jeder sie manipulieren kann. Die erweiterten Funktionen beheben das bei jedem Schritt: PAR und JAR schützen die Anfrage, private_key_jwt schützt die Identität der Anwendung, JARM schützt die Antwort, DPoP schützt das Token nach der Ausstellung, und CIBA behandelt den Fall ohne Browser. Hinzu kommen resource (welche API), RAR (welche genaue Operation), acr (welche Authentifizierungsstufe) und die dynamische Registrierung von Clients.
private_key_jwt · PAR · JAR · JARM · DPoP · CIBA · Resource Indicators · RAR · acr und Step-up · Dynamische Client-Registrierung · Pairwise und signiertes userinfo
RFC 7523 / OIDC Core 9
Beweisen Sie, wer Sie sind, mit einer Signatur statt einem gemeinsamen Passwort.
Ein vertraulicher Client authentifiziert sich normalerweise mit einem „client_secret“, einem Passwort, das Client und Server beide kennen. Gelangt es auf einer Seite nach außen, kann die andere es nicht wissen, und das Geheimnis wandert durch Konfigurationsdateien.
Der Client behält einen privaten Schlüssel, der seine Räumlichkeiten nie verlässt. Bei jedem Aufruf baut er ein kleines signiertes „Zeugnis“ (ein JWT): „Ich bin dieser Client, ich wende mich an diesen Server, und das gilt nur wenige Minuten.“ Der Server hat nur den öffentlichen Schlüssel: Er prüft die Signatur, mehr nicht.
Als Bild
Statt eines Passworts, das der Wächter kennt, signieren Sie jeden Eintritt mit Ihrem persönlichen Stift; der Wächter hat nur eine Unterschriftsprobe.
Banken, öffentliche Verwaltungen, jede Umgebung, die gemeinsame Geheimnisse verbietet. In mehreren Sicherheitsprofilen (FAPI) verpflichtend.
Wiedergegebene Assertion (daher der einmalige Bezeichner „jti“), falsche Audience, zu lange Lebensdauer, falscher Schlüssel.
Erstellen Sie in Ihrem Test-Provider einen Client „Vertraulich mit Schlüssel (private_key_jwt)“, fügen Sie Ihr Zertifikat oder öffentliches JWKS ein und rufen Sie dann /token mit client_assertion auf. ID-Kit sagt Ihnen genau, warum eine Assertion abgelehnt wird.
RFC 9126
Ihre Anmeldeanfrage direkt an den Server senden, ohne über den Browser zu gehen.
Normalerweise steht die Anfrage (wer ich bin, was ich will, wohin zurück) in der Seitenadresse und läuft über den Browser: Benutzer oder Schadsoftware können sie lesen oder ändern, und sehr lange Adressen sind ein Problem.
Die Anwendung sendet zuerst ihre gesamte Anfrage von Server zu Server an den Server und authentifiziert sich dabei. Der Server antwortet mit einem einfachen „Ticket“ (request_uri), eine Minute gültig. Die Anwendung schickt dann den Browser nur mit diesem Ticket zum Server. Das Ticket ist nur einmal verwendbar.
Als Bild
Statt Ihre Bestellung quer durch den Speisesaal zu rufen, geben Sie sie der Küche und zeigen dem Saal nur eine Ticketnummer.
Immer wenn Sie verhindern wollen, dass ein Parameter manipuliert wird (Betrag, Scopes, redirect_uri): Banken, Gesundheitswesen, Zahlungen. Von FAPI gefordert.
Ticket abgelaufen (60 s), bereits verwendet oder von einem anderen Client vorgelegt als dem, der es eingereicht hat.
Test-Provider: Rufen Sie /par auf. Wählen Sie bei der Testanwendung den Flow „code_par“. Die Einstellung „Require PAR“ des Providers lehnt klassische Anfragen ab.
RFC 9101
Die Anmeldeanfrage signieren, damit niemand sie unterwegs ändern kann.
Selbst mit den Parametern in der Adresse beweist nichts, dass sie wirklich von der Anwendung stammen und nicht geändert wurden.
Die Parameter werden in einem mit dem Schlüssel des Clients signierten JWT gebündelt (Parameter „request“). Der Server prüft Signatur, Issuer, Audience und Datum. Die Parameter des JWT ersetzen die der Adresse.
Als Bild
Ein Brief in einem mit Wachs versiegelten Umschlag: Ist das Siegel gebrochen, sieht es der Server.
Mit PAR in Hochsicherheitsprofilen; allein, wenn es keinen Server-zu-Server-Kanal gibt.
Öffentlicher Client-Schlüssel nicht registriert, „aud“ ist nicht der Issuer des Servers, abgelaufenes JWT, abweichende client_id.
Registrieren Sie den öffentlichen Schlüssel des Clients und senden Sie dann Ihr JWT in „request“ oder an /par. Falsche Signaturen und Audiences werden erklärt.
FAPI JARM
Der Server signiert auch seine Antwort: Die Anwendung weiß, dass sie wirklich von ihm stammt und nicht verändert wurde.
Wenn der Server den Benutzer mit „code=…“ in der Adresse zur Anwendung zurückschickt, kann jeder im Browser daran herumfummeln. Das öffnet die Tür für Angriffe, bei denen ein anderer Server den richtigen imitiert („Mix-up“).
Statt mehrerer einfacher Parameter liefert der Server einen einzigen Parameter „response“: ein signiertes JWT mit code, state, dem Issuer (iss) und der Audience (aud). Die Anwendung prüft die Signatur und liest dann den darin enthaltenen Code. Vier Varianten: jwt, query.jwt, fragment.jwt, form_post.jwt (je nachdem, wo das JWT platziert wird).
Als Bild
Die Antwort kommt in einem versiegelten Umschlag statt auf einer Postkarte.
FAPI-2.0-Profil und regulierte Branchen. Auch nützlich, um Mix-up-Angriffe zwischen Servern zu erkennen.
Die Signatur nicht prüfen oder einfache Parameter neben dem JWT lesen. query.jwt ist verboten, wenn Token über den Browser zurückkommen.
Fügen Sie response_mode=jwt (oder eine Variante) zu Ihrer Autorisierungsanfrage beim Test-Provider hinzu: Auch eine Ablehnung oder ein Fehler wird signiert.
RFC 9449
Ein gestohlenes Token ist ohne den Schlüssel der Anwendung, die es angefordert hat, nutzlos.
Ein „Bearer“-Token funktioniert wie Bargeld: Wer es hält, kann es nutzen, auch wenn er es aus einem Log, einer Browser-Erweiterung oder einer kompromittierten API gestohlen hat.
Die Anwendung erzeugt ein Schlüsselpaar. Bei jedem Aufruf hängt sie einen kurzen, mit ihrem privaten Schlüssel signierten „Nachweis“ an: „Hier sind Methode und Adresse, die ich aufrufe, in diesem Augenblick.“ Der Server bindet das Token an den Fingerabdruck des Schlüssels (cnf.jkt). Die API prüft, dass der Nachweis vom selben Schlüssel signiert wurde und den Hash des Tokens (ath) trägt. Ein Dieb, der das Token, aber nicht den privaten Schlüssel hat, ist blockiert.
Als Bild
Eine Bankkarte mit PIN statt Geldscheinen: Die Karte allein genügt nicht.
Mobile Apps und Webseiten (SPA), bei denen Token exponiert sind, sensible APIs, FAPI-2.0-Profile.
Wiedergegebener Nachweis (einmaliges jti), falsche Methode oder Adresse (htm, htu), verstellte Uhr (iat ±2 Min.), Token mit „Bearer“ statt „DPoP“ vorgelegt, ath bei der API fehlt.
Senden Sie einen DPoP-Header an /token des Test-Providers: Das Token wird zu token_type DPoP mit cnf.jkt. Bei /userinfo benötigen Sie „Authorization: DPoP“ plus einen Nachweis mit ath, sonst erklärt eine Meldung, was fehlt.
OpenID CIBA Core
Eine Anwendung bittet den Server, jemanden auf seinem Telefon zu authentifizieren, ohne Browser oder Weiterleitung.
An einem Schalter, in einem Callcenter, an einem Zahlungsterminal oder bei einem Sprachassistenten sitzt die Person nicht vor einem Browser, der weiterleiten kann.
Die Anwendung sagt dem Server „authentifiziere Alice“ (login_hint), optional mit einer anzuzeigenden Nachricht („Zahlung von 25 € autorisieren?“), und erhält eine auth_req_id. Der Server kontaktiert Alice auf ihrem Telefon. Währenddessen fragt die Anwendung /token ab: „authorization_pending“, solange Alice nicht geantwortet hat, dann die Token, wenn sie akzeptiert, oder „access_denied“, wenn sie ablehnt.
Als Bild
Der Verkäufer ruft Ihre Bank an und sagt „mein Kunde ist hier“, und Ihre Bank schickt Ihnen eine Benachrichtigung zur Bestätigung.
Bestätigung von Zahlungen oder sensiblen Operationen, Callcenter, Terminals, Telefonie. Die Bindungsnachricht (binding_message) erscheint auf beiden Bildschirmen, um zu prüfen, dass die richtige Operation bestätigt wird.
Zu schnell abfragen (slow_down), die Anfrage ablaufen lassen, vergessen, dass login_hint einen dem Server bekannten Benutzer bezeichnen muss.
Aktivieren Sie den CIBA-Flow bei einem Client des Test-Providers und rufen Sie /bc-authorize auf. Die Antwort enthält einen Link „idkit_approval_url“: Das ist die „Telefon“-Seite, auf der Sie genehmigen oder ablehnen; danach holen Sie die Token mit /token. ID-Kit unterstützt nur den Poll-Modus.
RFC 8707
Sagen Sie, mit welcher API Sie sprechen wollen, damit das Token nur dort funktioniert.
Ein für „jede API“ gültiges Access-Token ist gefährlich: Wird die Abrechnungs-API kompromittiert, kann sie das Token gegen die Gehalts-API wiederverwenden.
Die Anwendung fügt ihrer Anfrage (Autorisierung oder Token) „resource=https://api.example.com/invoices“ hinzu. Der Provider setzt diese Adresse in die Audience (aud) des Tokens. Die API prüft, dass aud sie selbst ist, und lehnt sonst ab.
Als Bild
Eine namentliche Zugfahrkarte für eine bestimmte Strecke statt eines überall gültigen Tickets.
Sobald mehrere APIs hinter demselben Provider stehen, und für sensible Token.
API, die aud nicht prüft; Ressource mit Fragment (#) oder die keine absolute Adresse ist (invalid_target).
Fügen Sie resource zu /authorize oder /token des Test-Providers hinzu: Die Audience des JWT-Tokens und der Introspection ändert sich. Die Ressource wird im Code gemerkt und beim Refresh beibehalten.
RFC 9396
Ein genaues Recht anfordern („25 € an X zahlen“) statt eines breiten Scopes („zahlen“).
Ein Scope wie „payments“ ist zu vage: Der Benutzer weiß nicht, was er genehmigt, und das Token erlaubt weit mehr als die vorgesehene Operation.
Die Anwendung sendet authorization_details: eine JSON-Liste von Objekten mit einem „type“ (zum Beispiel payment_initiation) und den Details der Operation (Betrag, Empfänger). Der Provider zeigt sie an, kopiert sie ins Token und in die Antwort, und die API liest sie.
Als Bild
Ein ausgefüllter Scheck (Betrag, Empfänger) statt eines Blankoschecks.
Zahlungen, Gesundheitswesen, feingranulare Delegation. In einigen Bankprofilen verpflichtend.
Ungültiges JSON oder fehlendes „type“ (invalid_authorization_details); API, die den Token-Inhalt ignoriert.
Senden Sie authorization_details an /authorize oder /token: ID-Kit validiert es und findet es im Token, in der /token-Antwort und in der Introspection wieder.
OIDC Core, RFC 9470
Wissen, wie stark sich die Person authentifiziert hat, und bei Bedarf mehr verlangen.
Sich mit einem Passwort anzumelden genügt nicht, um 10 000 € zu überweisen. Die Anwendung muss sagen können „ich will starke Authentifizierung“.
Die Anwendung fragt acr_values an (zum Beispiel die Stufe „mfa“). Der Provider liefert im ID-Token den erreichten acr-Wert und die Liste amr der verwendeten Methoden (Passwort, Einmalcode…). Eine API kann ein Token zu niedriger Stufe ablehnen und ein „Step-up“ verlangen: Die Person muss sich stärker authentifizieren.
Als Bild
In der Bank dürfen Sie mit Ihrer Karte Ihr Konto einsehen, aber für eine große Überweisung wird zusätzlich ein Ausweis verlangt.
Sensible Operationen, Compliance (starke Authentifizierung).
acr_values als Anforderung behandeln, obwohl es eine Bitte („freiwillig“) ist; das erhaltene acr nicht prüfen.
Fügen Sie acr_values=urn:idkit:acr:mfa hinzu: Das ID-Token enthält acr und amr [pwd, otp], und die Introspection liefert acr und auth_time. Ohne Anfrage ist die Stufe „pwd“.
RFC 7591
Eine Anwendung registriert sich selbst beim Provider, ohne über einen Administrator zu gehen.
Clients von Hand anzulegen skaliert nicht: Werkzeuge, Erweiterungen, MCP-Server, mobile Apps, die von Tausenden installiert werden.
Die Anwendung sendet einen JSON-POST an /register (Name, Rückkehradressen, gewünschte Abläufe, Authentifizierungsmethode). Der Provider legt den Client an und liefert client_id und gegebenenfalls client_secret.
Als Bild
Ein Selbstbedienungs-Anmeldeterminal statt eines Termins am Empfang.
Offene Ökosysteme, Werkzeuge, die sich an unbekannte Provider anschließen.
Unsichere Weiterleitungen (http außerhalb von localhost), zur Authentifizierungsmethode inkonsistente Grants, kein Limit.
Aktivieren Sie „Allow dynamic registration“ in den Einstellungen des Test-Providers und senden Sie dann einen POST an /register. Das Limit beträgt 25 Clients.
OIDC Core 8.1 und 5.3.2
Ein anderer Bezeichner pro Anwendung und signierte Profilinformationen.
Sehen alle Anwendungen denselben Bezeichner (sub) einer Person, können sie ihre Datenbanken abgleichen und sie von einem Dienst zum anderen verfolgen.
Im Pairwise-Modus berechnet der Provider für jede Anwendungsdomain ein anderes sub: Derselbe Benutzer erscheint bei zwei Anwendungen unter zwei verschiedenen Bezeichnern. Unabhängig davon kann /userinfo mit einem signierten JWT statt einfachem JSON antworten, damit die Anwendung die Herkunft der Informationen nachweisen kann.
Als Bild
Ein anderes Pseudonym pro Website statt einer Sozialversicherungsnummer überall.
Datenschutz (öffentliche Verwaltungen, Gesundheitswesen, Bildung); Umgebungen, in denen Profilinformationen signiert sein müssen.
Konten über Anwendungen hinweg mit sub verknüpfen (mit Pairwise unmöglich); vergessen, dass das sub in userinfo mit dem im ID-Token identisch sein muss.
Zwei Einstellungen beim Test-Provider: „Bezeichner pro Anwendung (pairwise)“ und „userinfo als signiertes JWT“.
Siehe auch: Sequenzdiagramme · welchen Ablauf wählen? · die Zeitleiste