OpenID Connect & OAuth 2.0, zum Durchklicken

Einen Ablauf auswählen und Schritt für Schritt durchgehen: Wer schickt was an wen, was steht in der Anfrage, was kommt zurück und was bedeutet jeder einzelne Parameter. Die Werte sind dabei nicht ausgedacht – die PKCE-Challenge ist der echte SHA-256 des Verifiers, das ID-Token ist in deinem Browser signiert. Den eigenen Provider kannst du über sein Discovery-Dokument einlesen.

Ablauf wählen

Beteiligte

Diese Angaben werden in alle Anfragen unten eingesetzt. Es wird nichts gesendet – der Provider ist nachgestellt, die Werte sind echt gerechnet.

Die Werte dieses Durchlaufs

state
nonce
code_verifier
code_challenge

Frisch erzeugt, jedes Mal anders. Die Challenge ist der tatsächliche SHA-256 des Verifiers – zum Nachrechnen und Weiterverwenden.

Wer redet mit wem

Nutzer / BrowserAnwendungProvider (IdP)Werte erzeugenRedirect /authorizeAnmeldung & ZustimmungRedirect mit codePOST /tokenTokensID-Token prüfenGET /userinfoRefresh
  • Front-Channel – läuft durch den Browser, ist sichtbar
  • Back-Channel – direkt von Server zu Server
  • passiert innerhalb eines Beteiligten
1 von 1

Das ID-Token aus diesem Durchlauf

Kein Textbaustein: Dieses Token wurde eben in deinem Browser mit einem frisch erzeugten RSA-Schlüssel signiert. Der at_hash passt wirklich zum Access Token oben, und mit dem JWK darunter lässt sich die Signatur prüfen.

Header

Payload

Die Claims im Einzelnen

FeldWert in diesem DurchlaufBedeutung
issWer das Token ausgestellt hat. Wird bei der Prüfung zeichengenau verglichen.
subDie unveränderliche Kennung des Nutzers beim Provider. Als Primärschlüssel geeignet – anders als die E-Mail-Adresse, die sich ändern kann.
audFür wen das Token bestimmt ist. Muss die eigene client_id enthalten.
expAb wann das Token nicht mehr gilt.
iatWann es ausgestellt wurde.
auth_timeWann sich der Nutzer tatsächlich angemeldet hat – kann deutlich früher liegen, wenn eine Sitzung wiederverwendet wurde.
nonceDer Wert aus der Anfrage. Bindet dieses Token an genau diesen Anmeldevorgang.
azpDie Partei, für die das Token gedacht ist. Relevant, wenn aud mehrere Einträge hat.
at_hashAbdruck des Access Tokens. Belegt, dass beide Tokens zusammengehören.
sidDie Sitzungs-ID beim Provider. Wird für Logout-Benachrichtigungen gebraucht.
nameAnzeigename. Gehört zum scope profile.
given_nameVorname, ebenfalls aus profile.
family_nameNachname, ebenfalls aus profile.
emailE-Mail-Adresse. Nur mit scope email.
email_verifiedOb der Provider die Adresse geprüft hat. Ohne dieses true taugt die Adresse nicht zur Zuordnung eines Kontos.

Passender JWKS-Eintrag (jwks_uri)

Deinen eigenen Provider einlesen

Jeder OpenID-Connect-Provider beschreibt sich selbst unter /.well-known/openid-configuration. Lade das Dokument oder füge es ein – die Felder werden erklärt, und die Endpunkte lassen sich in die Simulation oben übernehmen.

Hinweis: „Laden“ ist der einzige Punkt in diesem Werkzeug, an dem dein Browser eine fremde Adresse aufruft – und nur, wenn du darauf klickst. Die Anfrage geht direkt von dir zum Provider, nicht über unseren Server. Eingefügtes JSON verlässt deinen Browser überhaupt nicht.

OAuth 2.0 oder OpenID Connect – was ist was?

Die beiden werden dauernd in einen Topf geworfen, beantworten aber verschiedene Fragen.OAuth 2.0 ist ein Berechtigungsverfahren: Es regelt, wie eine Anwendung Zugriff auf fremde Daten bekommt, ohne das Passwort zu kennen – „diese App darf meinen Kalender lesen“. Über den Menschen dahinter sagt es bewusst nichts.

OpenID Connect ist eine dünne Schicht darüber und ergänzt genau das fehlende Stück: die Anmeldung. Technisch sind es im Wesentlichen drei Zutaten – der Scope openid, ein zusätzliches Token in der Antwort (das ID-Token) und ein festgelegter Satz von Endpunkten. Alles andere ist OAuth. Wer den Code-Flow von OAuth verstanden hat, versteht OIDC in fünf Minuten mit.

Die praktische Konsequenz steht in der Fehlerliste vieler Projekte: Ein Access Token istkein Anmeldenachweis. Es bezeugt eine Erlaubnis, nicht eine Identität, und es ist nicht für die Anwendung ausgestellt, sondern für die API dahinter. Wer sich mit einem Access Token anmeldet, baut sich eine Lücke ein – das ID-Token ist das Stück, das dafür vorgesehen ist.

Welchen Ablauf brauche ich?

AnwendungAblaufWarum
ServeranwendungAuthorization Code + PKCEKann ein client_secret wirklich geheim halten. PKCE trotzdem mitnehmen – es kostet nichts und schützt gegen abgefangene Codes.
SPA im BrowserAuthorization Code + PKCEÖffentlicher Client, also ohne Secret. PKCE ersetzt es vollständig.
Mobile- oder Desktop-AppAuthorization Code + PKCEIm Systembrowser, nicht im eingebetteten WebView – sonst sieht die App das Passwort doch wieder.
Fernseher, Konsole, CLIDevice Authorization GrantVerlagert die Eingabe auf ein Gerät mit Tastatur und Browser.
Hintergrunddienst, CronjobClient CredentialsKein Mensch beteiligt, also auch keine Anmeldung und kein ID-Token.
Bestandssystem mit response_type=tokenImplicit – umstellenGilt als überholt und fehlt in OAuth 2.1. Der Ersatz ist derselbe Code-Flow wie überall sonst.

state, nonce und PKCE: drei Zufallswerte, drei verschiedene Aufgaben

Sie sehen gleich aus – alle drei sind Zufallszeichenketten, die hin- und zurückgehen – und werden deshalb regelmäßig verwechselt oder als redundant abgetan. Sie sichern aber drei völlig verschiedene Dinge ab, und keiner ersetzt einen anderen.

WertLiegt beiVerhindert
stateClient-SitzungDass jemand dem Nutzer einen fremden Rücksprung unterschiebt und ihn so in ein fremdes Konto einloggt (CSRF).
nonceClient-Sitzung, später im ID-TokenDass ein anderswo erbeutetes, gültiges ID-Token ein zweites Mal eingespielt wird.
code_verifierNur im ClientDass ein abgefangener Autorisierungscode von jemand anderem eingelöst wird.

Der Unterschied lässt sich auch am Weg festmachen: state und nonce reisen offen durch den Browser und werden beim Zurückkommen verglichen. Der code_verifierreist überhaupt nicht durch den Browser – unterwegs ist nur sein Abdruck. Deshalb ist PKCE der einzige der drei Mechanismen, der auch dann noch trägt, wenn ein Angreifer den kompletten Front-Channel mitliest.

ID-Token, Access Token, Refresh Token

TokenEmpfängerBeantwortetLebensdauer
ID-Tokender ClientWer hat sich angemeldet, wann und wie?Minuten – es wird einmal geprüft, nicht aufbewahrt
Access Tokendie APIWas darf der Aufrufer?Minuten bis Stunden
Refresh Tokender ProviderDarf ich neue Tokens haben?Tage bis Monate

Daraus folgen zwei Regeln, die oft verletzt werden. Erstens: Ein ID-Token gehört niemals alsAuthorization-Header an eine API. Es ist für den Client ausgestellt (audist die client_id), und eine API, die es trotzdem akzeptiert, prüft die falsche Zielgruppe. Zweitens: Ein Client soll das Access Token nicht auswerten. Es mag ein lesbares JWT sein, muss es aber nicht – das Format gehört dem Provider und der API und kann sich jederzeit ändern.

Scopes und Claims

Ein Scope ist das, wonach gefragt wird; ein Claim das, was zurückkommt. OpenID Connect definiert dafür feste Pakete: profile bringt Name, Bild und Sprache mit, email die Adresse samt email_verified,address und phone entsprechend. offline_access ist der Sonderfall – es fragt nicht nach Daten, sondern nach einem Refresh Token.

Bei email_verified lohnt ein zweiter Blick: Ist der Wert nicht true, darf die Adresse nicht zur Zuordnung eines bestehenden Kontos dienen. Andernfalls genügt es, bei einem Provider ohne Adressprüfung ein Konto mit fremder Adresse anzulegen, um sich in das Konto eines anderen einzuloggen. Stabil ist allein die Kombination aus iss und sub.

Discovery: die Selbstauskunft des Providers

Unter /.well-known/openid-configuration beschreibt jeder OpenID-Connect-Provider sich selbst: Endpunkte, unterstützte Scopes, Signaturverfahren, PKCE-Methoden. Für eine Integration ist das die zuverlässigste Quelle – zuverlässiger als die Dokumentation, denn das Dokument kommt aus dem laufenden System. Das Werkzeug oben liest es ein, erklärt jedes Feld und beantwortet daraus gleich die üblichen Fragen: Wird S256 unterstützt? Gibt es den Device Flow? Werden unsignierte ID-Tokens angeboten (was ein Warnsignal wäre)?

Ein Detail entscheidet über die Sicherheit der ganzen Kette: Der issuer im Dokument muss zu der Adresse passen, unter der das Dokument liegt. Später wird der iss-Claim jedes ID-Tokens genau gegen diesen Wert geprüft – zeichengenau, nicht „fängt an mit“.

Abmelden ist schwerer als anmelden

Der lokale Logout ist trivial: Sitzung des Clients verwerfen, fertig. Nur ist der Nutzer damit weiterhin beim Provider angemeldet – der nächste Anmeldeversuch läuft ohne jede Rückfrage durch und wirkt wie ein Fehler. Dafür gibt es das RP-Initiated Logout über denend_session_endpoint, mit id_token_hint undpost_logout_redirect_uri.

Umgekehrt ist es noch unangenehmer: Meldet sich jemand beim Provider ab, sollen es alle angeschlossenen Anwendungen erfahren. Der Front-Channel-Weg dafür (versteckte iframes) hängt an Drittanbieter-Cookies und verschwindet mit ihnen; verlässlich ist nur Back-Channel Logout, bei dem der Provider jede Anwendung serverseitig benachrichtigt. Dafür braucht der Client einen erreichbaren Endpunkt – eine reine SPA ohne Backend kann das nicht leisten.

Häufige Fragen

Wird hier irgendetwas an einen Server geschickt?
Nein. Der Provider im Werkzeug ist nachgestellt, alle Werte entstehen in deinem Browser. Die einzige Ausnahme ist die Schaltfläche „Laden“ im Discovery-Bereich: Sie ruft die Adresse auf, die du dort einträgst – direkt von deinem Browser zu diesem Provider, nicht über unseren Server. Eingefügtes JSON verlässt deinen Browser gar nicht.

Kann ich das Werkzeug gegen meinen echten Provider laufen lassen?
Nicht als vollständigen Anmeldevorgang – dafür bräuchte es eine registrierteredirect_uri und hieße, fremde Tokens in einer fremden Seite entgegenzunehmen. Was du tun kannst: das Discovery-Dokument einlesen, die Endpunkte übernehmen und die entstehenden Anfragen mit denen deiner eigenen Anwendung vergleichen. Erfahrungsgemäß findet man den Unterschied genau dort – ein fehlender nonce, ein redirect_uri, der sich um einen Schrägstrich unterscheidet.

Ist das ID-Token oben echt?
Ja. Es wird beim Laden der Seite mit einem frisch erzeugten RSA-Schlüssel über die Web-Crypto-API signiert; der ausgegebene JWK-Satz gehört dazu und prüft die Signatur erfolgreich. Auch derat_hash ist wirklich über das daneben stehende Access Token gerechnet. Zum Gegenprüfen: JWT-Decoder.

Warum liefert Client Credentials kein ID-Token?
Weil es niemanden gibt, über den etwas zu bezeugen wäre. Ein ID-Token ist die Aussage „diese Person hat sich hier und jetzt angemeldet“. Bei einem Hintergrunddienst gibt es keine Person, nur eine Anwendung, die sich selbst ausweist. Deshalb ist dieser Ablauf reines OAuth 2.0 und gar kein OpenID Connect.

Brauche ich PKCE auch mit einem client_secret?
Ja, und die Empfehlung der IETF ist hier eindeutig. Das Secret schützt den Token-Endpunkt, PKCE schützt den Autorisierungscode auf seinem Weg durch den Browser – zwei verschiedene Strecken. Der Aufwand dafür sind zwei zusätzliche Parameter, die jede Bibliothek ohnehin schon setzt.