Einleitung
Wenn man Webentwicklung schon länger macht, kennt man das Muster: Loginformular → Benutzername + Passwort → Session-Cookie – und alles funktioniert. Bis zu dem Moment, wo man plötzlich eine API braucht, eine Mobile-App hinzukommt oder externe Partner sich anbinden sollen. Dann merkt man schnell: Das alte Modell stößt an Grenzen.
Ich bin in diesen Themen schon öfter mit OAuth in Berührung gekommen – allerdings meist aus der Konsumentenperspektive: „Login mit GitHub“, „Zugriff über ein API-Token“, all diese Dinge, die im Alltag so selbstverständlich wirken. Doch hinter diesen einfachen Klicks steckt ein komplexes Geflecht aus Protokollen, Tokens und Sicherheitsmechanismen.
Aus einer gewissen Unzufriedenheit mit den bestehenden Lösungen – oft zu proprietär, zu schwergewichtig oder schlicht zu komplex für kleine, dezentrale Edge-Anwendungen – entstand der Wunsch, das Thema wirklich zu verstehen. Mein Ziel: einen eigenen, schlanken Auth-Service zu entwickeln, der offen, nachvollziehbar und robust ist.
Dafür braucht es ein tiefes Verständnis der zugrunde liegenden Prinzipien – und genau hier setzt dieser Artikel an: eine kompakte und nachvollziehbare Erklärung, wie ich sie mir selbst gewünscht hätte.
1. Klassisches Login: vertraut, aber begrenzt
Beim klassischen Web-Login läuft alles in einem geschlossenen System:
Browser --> POST /login (username, password)
Server --> Set-Cookie: session_id=abc123
Browser --> nutzt Cookie für alle weiteren Requests
Das ist bequem, aber problematisch, sobald man aus der „einen Anwendung“ herauswächst.
Wo es knirscht:
- Mehrgerätewelt: Nutzer sind gleichzeitig in Web, Mobile und Desktop aktiv – Cookies funktionieren nicht überall gleich.
- APIs & Microservices: Eine Session ist an einen Server gebunden, nicht an einen verteilten Verbund.
- Sicherheit: Session Hijacking, CSRF und Session-Leaks sind notorische Dauerbrenner.
- Integrationen: Externe Dienste sollen Benutzer autorisiert, aber nicht direkt „einloggen“ können.
2. Warum moderne Systeme auf Tokens setzen
Statt einer Session im Server zu speichern, packt man heute alle nötigen Informationen in ein Token, das beim Request mitgeschickt wird.
| Eigenschaft | Session-Cookie | Token (z. B. JWT) |
|---|---|---|
| Speicherung | Serverseitig | Im Client (Header, Storage) |
| Zustand | Stateful | Stateless |
| Gültigkeit | Bis Logout oder Timeout | Zeitlich begrenzt (exp) |
| Überprüfung | Nur am Auth-Server möglich | An jeder API validierbar |
| Skalierbarkeit | Eingeschränkt | Hoch (keine zentrale Session) |
Client --> Authorization: Bearer <token>
API --> prüft Signatur + Ablaufzeit
3. Vom Eigenbau zu Standards: OAuth 2.0 & OpenID Connect
Früher hat jede Anwendung ihre eigene Login-Logik gebaut. Heute gibt es etablierte Standards:
- OAuth 2.0 → regelt die Autorisierung (Darf App X auf Ressource Y zugreifen?)
- OpenID Connect (OIDC) → ergänzt die Authentifizierung (Wer ist der Nutzer?)
Zentrale Rollen dabei:
| Rolle | Beschreibung |
|---|---|
| Resource Owner | Der Nutzer, dessen Daten geschützt sind |
| Client | Die Anwendung, die im Auftrag des Nutzers handelt |
| Authorization Server | Führt Login durch und stellt Tokens aus |
| Resource Server (API) | Prüft Tokens und liefert Daten |
4. Authorization Code Flow mit PKCE – Schritt für Schritt
Der Authorization Code Flow ist der Standard für Browser- und Mobile-Apps. Er besteht aus drei klaren Phasen: Login, Token-Austausch und API-Zugriff.
🧩 Phase 1: Login & Code-Erzeugung
Teilnehmer: Nutzer | Client | Authorization Server
Nutzer Client Auth-Server
| | |
| 1) App öffnen | |
|--------------->| |
| | 2) GET /authorize?... |
| |-------------------------->|
| | 3) Login-UI anzeigen |
| |<--------------------------|
| 4) Login-Daten eingeben |
|--------------->| |
| | 5) Weiterleiten an Auth |
| |-------------------------->|
| | | 6) Prüfe Nutzer & Consent
| |<--------------------------| 7) Redirect (callback)
| | | mit code=abc123&state=xyz
Der Nutzer wird vom Client an den Authorization Server weitergeleitet, um sich anzumelden.
Nach erfolgreichem Login prüft der Server Identität und Zustimmung (Consent) und erzeugt einen einmaligen Authorization Code.
Dieser wird per Redirect (Callback) an den Client zurückgegeben und dient als temporärer Nachweis des erfolgreichen Logins.
Der Redirect erfolgt an die registrierte redirect_uri des Clients.
Mit diesem Code kann der Client in der nächsten Phase sicher Tokens anfordern – ohne Passwörter oder Sitzungen weiterzugeben.
🧩 Phase 2: Token-Austausch mit PKCE
Teilnehmer: Client | Authorization Server
Client Auth-Server
| |
| 1) POST /token |
| grant_type=authorization_code
| code=abc123 |
| code_verifier=<PKCE> |
|---------------------------->|
| | 2) Validiere Code & PKCE
| | 3) Signiere Tokens (Access, ID, Refresh)
|<----------------------------| 4) Token Response
| |
Der Client tauscht den erhaltenen Authorization Code gegen echte Tokens aus. Er sendet dazu eine Anfrage an den Token-Endpoint des Authorization Servers, inklusive des zuvor erzeugten PKCE-Verifiers. Der Server prüft, ob Code und Verifier zusammenpassen, signiert die neuen Tokens und gibt sie zurück. Das Ergebnis sind ein Access Token (für API-Aufrufe), ein ID Token (Identität des Nutzers) und optional ein Refresh Token (zur späteren Erneuerung).
🧩 Phase 3: Zugriff auf die API
Teilnehmer: Client | Resource Server (API)
Client API
| |
| 1) GET /resource |
| Authorization: Bearer <access_token>
|--------------------------->|
| | 2) Verifiziere Token:
| | - Signatur gültig?
| | - Claims: exp, iss, aud, scope
| | 3) Zugriff erlauben oder verweigern
|<---------------------------| 4) 200 OK (Daten) / 401–403 Fehler
| |
Der Client nutzt jetzt das erhaltene Access Token, um eine geschützte API-Ressource anzufragen. Der Resource Server (also die API) prüft das Token selbstständig: Signatur, Ablaufzeit und Claims müssen stimmen. Ist alles gültig, werden die angeforderten Daten zurückgegeben – andernfalls folgt eine 401/403-Antwort.
5. Machine-to-Machine: Client Credentials Flow
Teilnehmer: Service A (Client) | Authorization Server | Service B (API)
Service A Auth-Server Service B
| | |
| 1) POST /token | |
| grant_type= | |
| client_credentials | |
| client_id=... | |
| client_secret=... | |
|--------------------------->| |
| | 2) Prüfe Client-ID |
| | & Secret |
| | Signiere Access Token |
|<---------------------------| access_token |
| |
| 3) GET /resource |
| Authorization: Bearer <access_token> |
|------------------------------------------------------->|
| | 4) Verifiziere
| | Token
| | (JWKS, Claims)
|<-------------------------------------------------------| 200 OK (Daten)
| |
Bei diesem Flow ist kein Nutzer beteiligt – ein technischer Client (z. B. ein Service oder Cronjob) authentifiziert sich direkt beim Authorization Server mit seiner client_id und seinem client_secret. Er erhält ein Access Token, mit dem er auf eine andere API zugreifen kann. So werden Service-zu-Service-Kommunikation und interne API-Aufrufe sicher geregelt – ganz ohne Benutzerkontext.
6. Refresh Tokens & Rotation
Teilnehmer: Client | Authorization Server
Client Auth-Server
| |
| 1) POST /token |
| grant_type=refresh_token |
| refresh_token=rt-xyz |
|---------------------------->|
| | 2) Prüfe Refresh Token:
| | - gültig?
| | - noch nicht verwendet?
| | 3) Rotiere Token:
| | - alten ungültig machen
| | - neuen Access & Refresh Token ausstellen
|<----------------------------| 4) Neue Tokens
| |
Wenn das Access Token abläuft, nutzt der Client sein Refresh Token, um neue Tokens zu erhalten – ohne dass sich der Nutzer erneut anmelden muss. Der Authorization Server prüft die Gültigkeit des Refresh Tokens, stellt neue Tokens aus und macht das alte Refresh Token sofort ungültig. Dieses Verfahren nennt man Token Rotation und verhindert, dass ein abgefangenes Token mehrfach verwendet werden kann.
7. Tokenprüfung und JWKS (API-Sicht)
Teilnehmer: API | OIDC Discovery | JWKS Endpoint
API Discovery JWKS
| | |
| 1) GET /.well-known/ | |
| openid-configuration | |
|-------------------------->| |
| | 2) Antwort mit |
| | jwks_uri |
|<--------------------------| |
| 3) GET /jwks.json (vom jwks_uri) |
|-------------------------------------------------->|
| 4) Antwort mit Keys [{ kid, ... }] |
|<--------------------------------------------------|
|
| Bei Request mit Bearer-Token:
| - Header.kid → passenden Schlüssel aus JWKS wählen
| - Signatur prüfen (z. B. Ed25519/RSA)
| - Claims prüfen: exp, nbf, iss, aud, scope
|
|→ 200 OK (erlaubt) oder 401/403 (verweigert)
Die Discovery-Abfrage liefert der API alle wichtigen Metadaten des Authorization Servers – darunter die URL des JWKS-Endpunkts, wo die öffentlichen Schlüssel hinterlegt sind. Anhand dieser Schlüssel kann die API später jedes JWT-Token prüfen, ohne sich direkt beim Authorization Server rückzuversichern.
8. Zusammenfassung: Bausteine moderner Authentifizierung
| Prinzip | Bedeutung |
|---|---|
| Statelessness | Keine Sitzungen, nur überprüfbare Tokens |
| Kurzlebigkeit | Tokens laufen schnell ab – Refresh statt Dauerlogin |
| Standardisierung | OAuth 2.0 / OIDC statt Eigenbau |
| PKCE | Schutz für Public Clients |
| JWKS | Öffentliche Schlüssel für Signaturprüfung |
| Rotation | Tokens und Keys regelmäßig erneuern |
Fazit
Moderne Authentifizierung ist kein Feature, sondern Architektur. Wer heute APIs entwickelt, sollte verstehen, dass Sicherheit und Vertrauen nicht mehr am Server kleben, sondern im Token stecken – überprüfbar, standardisiert, unabhängig vom Systemkontext.
OAuth 2.0 und OpenID Connect bieten dafür den Rahmen: Sicher, interoperabel, transparent.
Offizielle Spezifikationen und Standards:
-
RFC 6749 – The OAuth 2.0 Authorization Framework Grundlegender Standard für OAuth 2.0-Flows (Authorization Code, Client Credentials, Refresh Token).
-
RFC 7636 – Proof Key for Code Exchange (PKCE) Erweiterung zum Schutz öffentlicher Clients vor Code-Interception-Angriffen.
-
OpenID Connect Core 1.0 Ergänzt OAuth 2.0 um Authentifizierung – definiert ID Token, UserInfo und Discovery.
-
RFC 8414 – OAuth 2.0 Authorization Server Metadata (OIDC Discovery) Beschreibt den
.well-known/openid-configuration-Endpoint und Metadatenstrukturen. -
RFC 7519 – JSON Web Token (JWT) Aufbau, Claims und Signaturvalidierung von JSON-basierten Tokens.
-
RFC 7517 – JSON Web Key (JWK) Definiert das JWKS-Format (
/jwks.json) zur Bereitstellung öffentlicher Signaturschlüssel. -
OAuth 2.1 Draft (IETF, ongoing) Fasst bewährte Sicherheitspraktiken zusammen (PKCE verpflichtend, Rotation, kurze Tokenlaufzeiten).