Zum Inhalt springen

OpenID-Connect-Ablauf im Diagramm: Authorization Code Flow, ID-Tokens und Discovery

Wie OpenID Connect OAuth 2.0 um die Anmeldung erweitert: Authorization Code Flow mit PKCE, das ID-Token und seine Validierung, Discovery, JWKS, UserInfo und Logout.

· Gründer & Entwickler

Veröffentlicht am

Sequenzdiagramm mit Benutzer, Browser, Relying Party und OpenID Provider. Dreizehn nummerierte Nachrichten decken Redirect, Login, Code-Austausch und Token-Antwort ab; ein critical-Fragment validiert das ID-Token, ein opt-Fragment ruft UserInfo auf.

Eine Mobile-App meldet einen Benutzer bei einem Identity Provider an und reicht das Access-Token an dein Backend weiter. Das Backend ruft den Profil-Endpunkt des Providers auf, bekommt eine E-Mail-Adresse und legt eine Session an. Alle Tests laufen durch. Damit kann sich aber auch jede andere App, bei der sich der Benutzer mit demselben Provider angemeldet hat, mit ihrem eigenen Access-Token als dieser Benutzer bei deiner App anmelden, weil nichts prüft, für welche App das Token ausgestellt wurde.

OpenID Connect (OIDC) schließt diese Lücke. Es ergänzt OAuth 2.0 um ein ID-Token: ein signiertes JWT, in dem der Provider angibt, wer der Benutzer ist, für welche App das Token bestimmt ist und wann sich der Benutzer angemeldet hat.

Dieser Beitrag zeichnet den Authorization Code Flow mit PKCE als Sequenzdiagramm und behandelt, was OIDC hinzufügt: den Scope openid, nonce, die Validierung des ID-Tokens, Discovery, Schlüsselrotation, UserInfo und Logout.

OAuth 2.0 vs. OpenID Connect

Bei OAuth 2.0 geht es um Zugriff: ein Token, um im Namen des Benutzers eine API aufzurufen. Bei OpenID Connect geht es um Identität: wer sich angemeldet hat.

OAuth 2.0 OpenID Connect
Beantwortete Frage Darf diese App diese API aufrufen? Wer ist der Benutzer, und wann hat er sich angemeldet?
Token Access-Token ID-Token
Token ist gedacht für Die API Deine App
Token-Format Nicht festgelegt: opak oder JWT Ein signiertes JWT
So fragst du an Scopes, die die API definiert scope enthält openid
Definiert Grants und Endpunkte Claims, UserInfo, Discovery, Logout

Auf HTTP-Ebene ist eine OIDC-Anmeldung ein OAuth-Autorisierungsrequest mit openid im Scope, und die Token-Antwort enthält neben dem Access-Token ein id_token. Das OAuth-2.0-Flow-Diagramm behandelt die OAuth-Hälfte im Detail.

Der Ablauf Schritt für Schritt

OpenID Connect Core 1.0 nennt deine App Relying Party (RP) und den Autorisierungsserver OpenID Provider (OP). Was durch den Browser läuft, der Front-Channel, kann in URLs, den Verlauf und Logs gelangen; Aufrufe von deinem Backend an den Provider, der Back-Channel, nicht. Die Nummern entsprechen dem Diagramm.

  1. Start (1–3). Der Benutzer klickt auf „Anmelden“. Deine App speichert frische Werte für state, nonce und den PKCE-code_verifier in der Session und leitet den Browser zum Provider weiter.
  2. Authentifizierungsrequest (4). Der Browser folgt dem Redirect:
GET /authorize?response_type=code
    &client_id=orders-web
    &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
    &scope=openid%20profile%20email
    &state=7fJq2LbX9aQe
    &nonce=n-0S6_WzA2Mj
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256 HTTP/1.1
Host: op.example.com
  1. Login und Einwilligung (5). Der Provider authentifiziert den Benutzer (Passwort, Passkey, MFA oder eine bestehende Session) und holt die Einwilligung ein. Deine App sieht nie Zugangsdaten.
  2. Code zurück (6–7). Der Provider leitet an die registrierte redirect_uri weiter, mit einem kurzlebigen code und demselben state, den deine App mit der Session vergleicht.
  3. Token-Request (8–9). Dein Backend sendet code, redirect_uri und code_verifier per POST zusammen mit seinen Client-Credentials. Der Provider prüft den Verifier gegen die Challenge und gibt ein id_token, ein access_token und oft ein refresh_token zurück.
  4. Validierung (10). Deine App validiert das ID-Token und holt Signaturschlüssel nur dann, wenn der darin genannte Schlüssel nicht im Cache liegt.
  5. UserInfo (11–12), optional. Nur wenn dem ID-Token Claims fehlen, die du brauchst.
  6. Session (13). Deine App legt ihre eigene Session an und setzt ein Cookie.

Wovor state, nonce und PKCE schützen

Wert Übertragen in Geprüft von Verhindert
state Schritt 4 und dem Redirect zurück Deine App Eine Login-Antwort, die der Benutzer nie gestartet hat (CSRF)
nonce Schritt 4, dann im ID-Token Deine App Replay des ID-Tokens und, bei vertraulichen Clients, Code-Injection
code_verifier Sein SHA-256-Hash in Schritt 4, der Wert selbst in Schritt 8 Der Provider Das Einlösen eines gestohlenen Codes

Die OAuth Security Best Current Practice, RFC 9700, erlaubt in manchen Fällen, dass ein Wert einen anderen ersetzt, aber jeder kostet nur einen Zufallswert, also schick alle drei. Öffentliche Clients wie Single-Page- und Mobile-Apps müssen PKCE (RFC 7636) mit S256 verwenden.

Ein Blick ins ID-Token

Das ID-Token aus Schritt 9, dekodiert:

{
  "iss": "https://op.example.com",
  "sub": "248289761001",
  "aud": "orders-web",
  "nonce": "n-0S6_WzA2Mj",
  "iat": 1793736400,
  "exp": 1793740000,
  "auth_time": 1793736390
}
Claim Bedeutung Deine App
iss Issuer, eine https-URL Muss exakt dem per Discovery ermittelten issuer entsprechen
sub Benutzer-ID, beim Issuer nie neu vergeben, höchstens 255 ASCII-Zeichen Nutzt iss plus sub als Kontoschlüssel
aud Audience, ein String oder ein Array Muss darin ihre client_id finden
exp, iat Ablauf- und Ausstellungszeit in Unix-Sekunden Lehnt abgelaufene oder sehr alte Tokens ab
nonce Der in Schritt 4 gesendete Wert Muss zur Session passen
auth_time Wann sich der Benutzer tatsächlich authentifiziert hat Prüft ihn, wenn du max_age sendest
acr, amr Vertrauensniveau und Methoden, etwa pwd oder mfa Prüft sie vor sensiblen Aktionen

Core stellt klar, dass nur iss plus sub einen Benutzer identifiziert: E-Mail-Adressen ändern sich und können neu vergeben werden.

Das ID-Token validieren

Abschnitt 3.1.3.7 von Core listet die Regeln auf:

  1. Fixiere den Algorithmus (standardmäßig RS256), statt dem alg-Header zu vertrauen, und akzeptiere niemals none.
  2. Prüfe die Signatur mit dem JWKS-Schlüssel, den kid nennt. Core erlaubt einem Client im Code Flow, sich stattdessen auf TLS zu verlassen, weil das Token direkt vom Token-Endpunkt kam, aber die Prüfung kostet wenig.
  3. Prüfe iss gegen den per Discovery ermittelten Issuer, Zeichen für Zeichen.
  4. Prüfe aud auf deine client_id und lehne Audiences ab, denen du nicht vertraust.
  5. Prüfe exp und iat und erlaube dabei Sekunden bis wenige Minuten Uhrenabweichung.
  6. Prüfe nonce gegen die Session und lösche den Wert danach.
  7. Prüfe auth_time und acr, wenn du sie angefordert hast.

Erst dann legst du eine Session an. Mit der Bibliothek jose in Node.js:

import { createRemoteJWKSet, jwtVerify } from 'jose'

// issuer and jwks_uri come from the discovery document.
// The key set is cached; an unknown kid triggers a refetch
// (at most once every 30 seconds by default).
const JWKS = createRemoteJWKSet(new URL(oidc.jwks_uri))

const { payload } = await jwtVerify(tokens.id_token, JWKS, {
  issuer: oidc.issuer,     // exact match
  audience: CLIENT_ID,     // must appear in aud
  algorithms: ['RS256'],   // never trust the header alone
  clockTolerance: 60,      // seconds of clock skew
  maxTokenAge: 600,        // rejects an old iat
})
if (payload.nonce !== session.nonce) throw new Error('nonce mismatch')

Discovery und Schlüsselrotation

OpenID Connect Discovery 1.0 legt die Einstellungen eines Providers in einem einzigen JSON-Dokument ab, erreichbar unter der Issuer-URL plus /.well-known/openid-configuration. Das Dokument von Google, gekürzt auf die Felder, die dieser Flow nutzt, zum Zeitpunkt des Schreibens (November 2026):

{
  "issuer": "https://accounts.google.com",
  "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
  "token_endpoint": "https://oauth2.googleapis.com/token",
  "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
  "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
  "id_token_signing_alg_values_supported": ["RS256"],
  "code_challenge_methods_supported": ["plain", "S256"]
}

Der issuer muss mit der Issuer-URL, von der du das Dokument abgerufen hast, und mit dem iss jedes ID-Tokens identisch sein. Konfiguriere den erwarteten Issuer selbst; übernimm ihn nie aus einem Token, das du nicht geprüft hast.

Schlüssel rotieren über die jwks_uri: Der Provider fügt einen neuen Schlüssel hinzu, signiert damit und lässt den alten noch eine Weile veröffentlicht (Core, Abschnitt 10.1.1). Cache das Schlüsselset, beachte Cache-Control, lade es bei einer unbekannten kid neu und begrenze die Rate dieser Neuabrufe. Das JWT-Authentifizierungs-Flow-Diagramm behandelt dieselbe Mechanik für Access-Tokens.

UserInfo

UserInfo liefert Claims für die gewährten Scopes (profile, email, address, phone), wenn du den Endpunkt mit dem Access-Token aufrufst. Die Antwort enthält immer sub, das exakt dem sub des ID-Tokens entsprechen muss, sonst verwirfst du die Antwort.

Logout-Optionen

Drei finale OpenID-Spezifikationen behandeln die Abmeldung:

Spezifikation So funktioniert sie Worauf du achten musst
RP-Initiated Logout 1.0 Deine App leitet mit id_token_hint zum end_session_endpoint des Providers weiter Deine App muss auch ihre eigene Session beenden
Front-Channel Logout 1.0 Der Provider lädt die Logout-URL jeder App in einem iframe Das Blockieren von Drittanbieter-Cookies kann es aushebeln
Back-Channel Logout 1.0 Der Provider schickt per POST ein signiertes Logout-Token an jede App Deine App muss die Session serverseitig finden und beenden

Core weist außerdem darauf hin, dass das exp des ID-Tokens nichts mit der Lebensdauer der Session zu tun hat.

Fehler, die in Reviews auffallen

  • Ein Access-Token als Identitätsnachweis. Die Szene vom Anfang. Melde Benutzer nur mit einem ID-Token an, das dein Backend vom Token-Endpunkt bekommen und validiert hat.
  • aud oder nonce nicht prüfen. Jede beim selben Provider registrierte App bekommt gültig signierte ID-Tokens mit demselben iss; nur aud sagt, dass ein Token für dich ausgestellt wurde, und nur nonce bindet es an diesen Login.
  • Der Implicit Flow. response_type=id_token token legt Tokens ins URL-Fragment; laut RFC 9700 sollten Clients keine Response Types verwenden, die Access-Tokens in der Autorisierungsantwort zurückgeben. Nutze code mit PKCE, auch in Single-Page-Apps.
  • ID-Tokens, die an APIs geschickt werden. APIs sollten nur Access-Tokens akzeptieren, die für sie ausgestellt wurden; das API-Gateway-Architekturdiagramm zeigt, wo diese Prüfung meist sitzt.

Das Diagramm zum OpenID-Connect-Ablauf

Sequenzdiagramm mit Benutzer, Browser, Relying Party und OpenID Provider. Dreizehn nummerierte Nachrichten decken Redirect, Login, Code-Austausch und Token-Antwort ab; ein critical-Fragment validiert das ID-Token, ein opt-Fragment ruft UserInfo auf.

16 Komponenten · 13 Verbindungen

In Archboard öffnen
Diagramminhalt
  • User
  • Browser
  • Relying party (your app)
  • OpenID provider
  • all checks must pass
  • claims missing from the ID token
  • ID token: for your app (aud = client_id)
  • Access token: for UserInfo and APIs
  • 1. Click Sign in
  • 2. GET /login
  • 3. 302 to the provider's /authorize
  • 4. GET /authorize: scope=openid, state, nonce, code_challenge
  • 5. Log in (password, passkey, MFA) and consent
  • 6. 302 to redirect_uri with code, state
  • 7. GET /callback?code&state
  • 8. POST /token: code, code_verifier, client auth
  • 9. id_token, access_token
  • 10. GET jwks_uri (when kid is not cached)
  • 11. GET /userinfo, Bearer access_token
  • 12. Claims; sub must match the ID token
  • 13. 302 to the app, Set-Cookie: session
Der OpenID Connect Authorization Code Flow mit PKCE. Deine App schickt den Browser mit scope=openid, state, nonce und einer Code Challenge zum Provider, tauscht den Code über den Back-Channel ein und validiert das ID-Token, bevor sie eine Session anlegt.

So liest du es:

  • Vier Teilnehmer: der Benutzer, der Browser, deine App (die Relying Party) und der OpenID Provider. Die Zeit läuft nach unten.
  • Farben zeigen den Kanal: Blau durch den Browser, Petrol von deinem Backend zum Provider, Violett für die Aktionen des Benutzers. Gestrichelte Pfeile sind Antworten und Redirects.
  • Schritte 3 und 4 tragen scope=openid, state, nonce und die PKCE-Challenge; Schritt 8 trägt den Verifier.
  • Das critical-Fragment enthält den Schlüsselabruf und die Prüfungen, die bestehen müssen, bevor eine Session existiert. Das opt-Fragment ist der UserInfo-Aufruf.
  • Die rechte Spalte ordnet Discovery-Felder den Schritten zu, listet die PKCE-Parameter auf, dekodiert ein ID-Token und zeigt, welches Token für wen bestimmt ist.

OpenID-Connect-Diagramme klar zeichnen

  • Gib dem Browser eine eigene Lebenslinie. Die Trennung zwischen Front- und Back-Channel ist die Sicherheitsgeschichte dieses Flows.
  • Schreib die geprüften Parameter an die Pfeile: state, nonce, code_challenge, code_verifier.
  • Schreib die Validierung aus. „Token validieren“ lässt sich nicht reviewen; „Signatur, iss, aud, exp, iat, nonce“ schon.
  • Sag, welches Token wohin geht, samt Audience. Viele OIDC-Bugs sind ein Token, das bei der falschen Partei gelandet ist.
  • Ein Flow pro Diagramm. Zeichne Login, Refresh und Logout getrennt, mit Platzhalter-IDs und -Tokens.

Das Sequenzdiagramm-Beispiel behandelt die Notation; das SAML-SSO-Flow-Diagramm zeigt das XML-basierte Protokoll, nach dem Enterprise-Kunden immer noch fragen.

In Archboard nachbauen

  1. Melde dich mit Google oder GitHub an und leg ein Diagramm an.
  2. Füge aus dem Sequenz-Pack einen Akteur für den Benutzer und drei gleich hohe Lebenslinie-Nodes hinzu: Browser, Relying party (your app) und OpenID provider.
  3. Zeichne die 13 Nachrichten als gerade, nummerierte Kanten von oben nach unten. Zeichne Antworten gestrichelt und färbe Front- und Back-Channel unterschiedlich.
  4. Füge aus dem Sequenz-Pack ein Kombiniertes Fragment mit dem Operator critical um den Schlüsselabruf und die Prüfungen hinzu und ein zweites Kombiniertes Fragment mit opt um den UserInfo-Aufruf.
  5. Füge neben der Relying Party Text aus dem Basis-Pack für die Session-Werte und Prüfungen hinzu, dazu eine Farblegende.
  6. Füge einen Markdown-Block aus dem Basis-Pack für Discovery, PKCE und ein dekodiertes ID-Token hinzu und zwei Token-Nodes aus dem Sicherheits-Pack für das ID-Token und das Access-Token.

Das Beispiel nutzt 9 Diagramm-Nodes und bleibt damit im Free-Plan. Dein KI-Agent kann es auch über MCP zeichnen.

FAQ

Was ist der Unterschied zwischen OAuth 2.0 und OpenID Connect? OAuth 2.0 gibt einer App ein Access-Token, um eine API aufzurufen. OpenID Connect setzt die Anmeldung obendrauf: den Scope openid, ein ID-Token, das sagt, wer der Benutzer ist, sowie standardisierte Discovery- und UserInfo-Endpunkte.

Ist ein ID-Token dasselbe wie ein Access-Token? Nein. Das ID-Token ist ein signiertes JWT für deine App, das sagt, wer sich angemeldet hat. Das Access-Token ist für APIs bestimmt, auch für UserInfo. Schick ID-Tokens nie an APIs und akzeptiere Access-Tokens nie als Login-Nachweis.

Brauche ich PKCE, wenn ich schon eine Nonce sende? Nutze beides. RFC 9700 schreibt PKCE für öffentliche Clients vor. Ein vertraulicher Client darf sich mit zusätzlichen Vorkehrungen auf die Nonce verlassen, aber PKCE verhindert, dass ein gestohlener Code eingelöst wird, während die Nonce einen eingeschleusten Code erst nach der Token-Antwort erkennt.

Wie validiere ich ein ID-Token? Prüfe die Signatur mit dem JWKS-Schlüssel, der zu seiner kid passt, und prüfe dann, dass iss dem Issuer entspricht, aud deine Client-ID enthält, exp nicht überschritten ist, iat aktuell ist und nonce zur Session passt.

Was ist /.well-known/openid-configuration? Das Discovery-Dokument von OpenID Connect. Es listet Issuer, Endpunkte, Algorithmen und jwks_uri eines Providers auf, sodass sich deine App über eine einzige URL selbst konfigurieren kann.

Kostenlos starten — ein Seat, keine Kreditkarte.

Ähnliche Beiträge

← Zurück zum Blog

In einer Minute ein Canvas öffnen

Melden Sie sich mit Google oder GitHub an. Kostenlos für einen Sitzplatz. Upgraden Sie, wenn das Team dazukommt.