Zum Inhalt springen

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
OAuth 2.0 und OIDC Sicherheit: Häufige Fehler und wie man sie vermeidet - Cybersicherheit und digitaler Schutz
Offensive Security

OAuth 2.0 und OIDC Sicherheit: Häufige Fehler und wie man sie vermeidet

OAuth 2.0 ist der Standard für delegierte Autorisierung - und eine häufige Quelle von Sicherheitslücken. Dieser Guide erklärt OAuth-Flows (Authorization Code, PKCE, Client Credentials), die häufigsten OAuth-Sicherheitsfehler (offene Redirects, CSRF, Authorization Code Interception), OIDC-Sicherheitsaspekte und Best Practices für sichere OAuth-Implementierungen.

Vincent Heinen Vincent Heinen Abteilungsleiter Offensive Services
10 Min. Lesezeit
OSCP+ OSCP OSWP OSWA

TL;DR

OAuth 2.0 und OIDC sind de-facto-Standards für delegierte Autorisierung, enthalten aber häufige Implementierungsfehler mit kritischen Folgen. Typische Schwachstellen sind offene Redirect-URIs, fehlender CSRF-Schutz durch den state-Parameter, das Fehlen von PKCE für SPAs und mobile Apps sowie unsichere Token-Speicherung in localStorage. Access Tokens gehören in HTTPOnly-Cookies oder in Speicher ohne XSS-Zugriff. Refresh-Token-Rotation, kurze Token-Laufzeiten und Server-side Token-Invalidierung schließen die häufigsten Angriffsvektoren.

Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 50).

Inhaltsverzeichnis (4 Abschnitte)

OAuth 2.0 ist überall: "Login with Google", "Verbinde mit GitHub", API-Zugriffe für Drittanbieter. Richtig implementiert ist OAuth sicher und bequem. Falsch implementiert entstehen kritische Sicherheitslücken - von Account-Takeover bis zu vollständiger API-Kompromittierung.

OAuth 2.0 Grundlagen - was tatsächlich passiert

OAuth 2.0 Rollen:
  Resource Owner:      Der User der Zugriffsrechte erteilt
  Client:             Die Anwendung die Zugriff beantragt (z.B. Kalender-App)
  Authorization Server: Stellt Tokens aus (Entra ID, Keycloak, Auth0)
  Resource Server:    API die mit Tokens geschützt ist (Google Calendar API)

Authorization Code Flow (Standard für Web-Apps):

  1. User klickt "Login mit Google"
  2. Client → Authorization Server:
     GET /authorize?
       response_type=code&
       client_id=my-app-123&
       redirect_uri=https://myapp.com/callback&
       scope=email+calendar.read&
       state=RANDOM-CSRF-TOKEN  ← WICHTIG!

  3. User meldet sich an + genehmigt Zugriff
  4. Authorization Server → Client (Redirect):
     GET https://myapp.com/callback?code=AUTH_CODE&state=RANDOM-CSRF-TOKEN

  5. Client → Authorization Server (Back-Channel):
     POST /token
       code=AUTH_CODE&
       redirect_uri=https://myapp.com/callback&
       client_id=my-app-123&
       client_secret=MY-SECRET  ← Nur der echte Client kennt das!

  6. Authorization Server → Client:
     {"access_token": "eyJ...", "expires_in": 3600}

  7. Client → Resource Server:
     GET /calendar/events
     Authorization: Bearer eyJ...

Warum Authorization Code Flow sicher ist:
  → Auth Code geht über Browser (unsicher), aber nutzlos ohne Client Secret
  → Access Token geht nur via Server-zu-Server (nie zum Browser)
  → state-Parameter: verhindert CSRF!

Die wichtigsten OAuth-Sicherheitsprobleme

Schwachstelle 1: Offene Weiterleitungen (Open Redirects)

Problem:
  Authorization Server erlaubt beliebige redirect_uri:
  Angriff:
  GET /authorize?
    response_type=code&
    client_id=my-app&
    redirect_uri=https://evil.com/steal ← beliebige URL erlaubt!
    &state=...

  Ergebnis: Authorization Code wird an Angreifer gesendet!
  → Auth Code + Client Secret = vollständiger Account-Takeover

Schutz:
  → redirect_uri MUSS exakt vorregistriert sein
  → Authorization Server muss Exact-Match prüfen (kein Wildcard!)
  → Beispiel: nur "https://myapp.com/callback" erlaubt
    NICHT: "https://myapp.com/*"
    NICHT: "https://*.myapp.com/callback"

Schwachstelle 2: Fehlendes CSRF-Schutz (state-Parameter)

Problem:
  Angreifer erstellt speziell präparierten OAuth-Link:
  Schickt User zu: GET /authorize?...&state=ATTACKER-CONTROLLED
  Wenn User seinen Account verbindet: Angreifer-Account verbunden!

Schutz:
  → state-Parameter: kryptografisch zufällig, in Session gespeichert
  → Bei Callback: state aus URL = state in Session?
  → Wenn nicht gleich: Angriff erkannt, Prozess abbrechen!

  Implementierung (Node.js):
  const state = crypto.randomBytes(32).toString('hex');
  req.session.oauthState = state;
  const authUrl = `${AUTH_SERVER}/authorize?...&state=${state}`;

  // Callback:
  if (req.query.state !== req.session.oauthState) {
    return res.status(400).json({error: 'CSRF detected!'});
  }

Schwachstelle 3: Authorization Code Interception

Problem:
  Mobile Apps: code kommt via Custom URL Scheme:
  myapp://callback?code=AUTH_CODE
  Anderes App mit gleichem URL-Scheme: Code abgefangen!

Schutz: PKCE (Proof Key for Code Exchange) - Pflicht für SPAs und Mobile!
  code_verifier = 32 random bytes (geheimgehalten!)
  code_challenge = BASE64URL(SHA256(code_verifier))

  1. Start Authorization:
     GET /authorize?
       ...&
       code_challenge=<SHA256_of_verifier>&
       code_challenge_method=S256

  2. Token Request:
     POST /token
       code=AUTH_CODE&
       code_verifier=ORIGINAL_VERIFIER  ← Nur der echte Client kennt das!

  → Abgefangener Auth Code nutzlos ohne code_verifier!

Schwachstelle 4: Unsichere Token-Speicherung

Problem:
  SPA speichert Access Token in localStorage:
  localStorage.setItem('token', accessToken);
  → XSS-Angriff: document.cookie oder localStorage auslesen → Token gestohlen!

Schutz:
  → Access Token: in memory-Variablen (nicht persistent)
  → Refresh Token: in HttpOnly Cookie (kein JS-Zugriff!)
  → SameSite=Strict: CSRF-Schutz für Cookies

  // FALSCH - XSS-anfällig:
  localStorage.setItem('access_token', token);

  // RICHTIG - Token in Memory:
  let accessToken = null;  // In-memory, verschwindet bei Reload

  // Refresh Token: Server setzt HttpOnly Cookie:
  res.cookie('refresh_token', refreshToken, {
    httpOnly: true,     // JavaScript kann nicht zugreifen
    secure: true,       // Nur HTTPS
    sameSite: 'strict', // CSRF-Schutz
    maxAge: 30 * 24 * 60 * 60 * 1000  // 30 Tage
  });

Schwachstelle 5: Zu weite Scopes

Problem:
  App fordert alle Berechtigungen an:
  scope=email+profile+contacts+calendar+drive+gmail

  Konsequenz: Kompromittierter Token = Zugriff auf alles!

Schutz:
  → Minimal Scope: nur was aktuell benötigt wird
  → Incremental Authorization: Scope erst bei Bedarf anfordern
  → Scope Transparency: User sieht was App tatsächlich braucht

  // Falsch: alles auf einmal
  scope: 'email profile contacts calendar drive admin'

  // Richtig: nur was benötigt wird
  scope: 'email'  // Beim Login
  // Später wenn User Kalender-Feature nutzt:
  scope: 'email calendar.readonly'  // Minimal!

OpenID Connect (OIDC) Sicherheit

OIDC = OAuth 2.0 + Authentifizierung (Identität):

Zusätzlich zu Access Token: ID Token (JWT):
  ID Token enthält: sub (User ID), email, name, issued at, expiry, nonce

OIDC-Schwachstellen:

1. ID Token nicht validiert:
   Problem: App vertraut ID Token ohne Signatur-Prüfung
   Angriff: Gefälschter ID Token → anderer User
   Schutz:
   → IMMER signierte ID Tokens (RS256 oder ES256)
   → IMMER Signatur prüfen (mit JWKS des Authorization Server)
   → IMMER Expiry prüfen
   → IMMER Audience (aud) prüfen

   Python (Keycloak + python-jose):
   from jose import jwks, jwt
   keys = requests.get('https://keycloak/realm/certs').json()['keys']
   payload = jwt.decode(
     id_token,
     keys,
     algorithms=['RS256'],
     audience='my-client-id',  # Pflicht!
     issuer='https://keycloak/realm'
   )

2. Nonce-Replay:
   Problem: Ohne nonce: ID Token kann wiederverwendet werden
   Schutz:
   → nonce = random, in Session gespeichert
   → nonce im ID Token muss nonce aus Session entsprechen

3. Implicit Flow (veraltet, unsicher):
   Problem: Access + ID Token kommen direkt zum Browser via URL-Fragment
   → Token in URL = in Browser History, Logs, Referrer-Header
   → KEIN verwenden! Ersetze durch Authorization Code Flow + PKCE

---

JWT-Sicherheit (da OIDC JWTs nutzt):

JWT-Struktur: Header.Payload.Signature (base64-encoded, nicht verschlüsselt!)
  Header: {"alg": "RS256", "typ": "JWT"}
  Payload: {"sub": "123", "email": "user@example.com", "exp": 1770000000}
  Signature: RSA/ECDSA signature über Header.Payload

JWT-Schwachstellen:

1. Algorithm Confusion (alg=none):
   Angriff: Header ändern zu {"alg": "none"}
   Signature weglassen
   → Unsichere Libraries akzeptieren das!
   Schutz:
   → Algorithmus explizit festlegen beim Validieren
   → "none" niemals erlauben

2. RS256 → HS256 Switch:
   Angriff: RS256 (asymmetrisch) zu HS256 (symmetrisch) wechseln
   → HS256-Schlüssel = öffentlicher Schlüssel (den Angreifer kennt!)
   Schutz:
   → Algorithmus beim Validieren explizit auf RS256 fixieren

3. Weak HS256 Secret:
   jwt.io Debugger + Brute-Force = geknacktes HS256 JWT
   Schutz:
   → HS256 Secret: min. 256 Bit (32 Byte) zufällig
   → Besser: RS256/ES256 (asymmetrisch)

4. JWT ohne Expiry:
   Schutz:
   → Immer exp Claim setzen
   → Kurze Expiry: Access Token 15-60 Minuten

OAuth für APIs - Client Credentials Flow

Machine-to-Machine Authentication (keine User-Interaktion):

Client Credentials Flow:
  Service A → Authorization Server:
  POST /token
    grant_type=client_credentials&
    client_id=service-a&
    client_secret=secret123&
    scope=api.read

  Authorization Server → Service A:
  {"access_token": "eyJ...", "expires_in": 3600}

  Service A → Service B:
  GET /internal-api/data
  Authorization: Bearer eyJ...

Sicherheitsprobleme:

1. Client Secret Rotation:
   → Secrets müssen rotiert werden (Mindestens jährlich!)
   → Rotation: neues Secret erstellen → deploymen → altes deaktivieren
   → Secret im Vault (nicht in Konfigurationsdatei!)

2. Scope-Kontrolle:
   → client_id:service-a darf NUR /api/read
   → Nicht: admin-API, User-Daten anderer Services

3. Mutual TLS (mTLS) statt Client Secret:
   → Noch sicherer: Service A authentifiziert sich mit Zertifikat
   → Client Secret: shared secret (kann geleakt werden)
   → mTLS: privater Schlüssel verlässt Service nie
   → Kubernetes: Istio Service Mesh mit mTLS

Best Practices Zusammenfassung:
  □ Authorization Code Flow + PKCE für alle Public Clients
  □ state-Parameter IMMER (CSRF-Schutz)
  □ redirect_uri: exaktes Matching, vorregistriert
  □ Tokens: kurze Lifetime, Refresh Token in HttpOnly Cookie
  □ Scopes: minimal, incremental authorization
  □ ID Token: immer vollständig validieren (sig + aud + exp + nonce)
  □ JWT: expliziter Algorithmus, kein "none", starkes Secret
  □ Client Secrets: in Vault, rotieren, minimale Scope

OAuth-Implementierungsfehler sind in der OWASP API Security Top 10 prominent vertreten. AWARE7 analysiert OAuth/OIDC-Implementierungen im Rahmen von Penetrationstests und Web-Application-Security-Reviews.

API-Sicherheitstest anfragen | Penetrationstest Web-Applikationen

Nächster Schritt

Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel — unverbindlich und kostenlos.

Kostenlos · 30 Minuten · Unverbindlich

Artikel teilen

Über den Autor

Vincent Heinen
Vincent Heinen

Abteilungsleiter Offensive Services

E-Mail

M.Sc. IT-Sicherheit mit über 5 Jahren Erfahrung in offensiver Sicherheitsanalyse. Leitet die Durchführung von Penetrationstests mit Spezialisierung auf Web-Applikationen, Netzwerk-Infrastruktur, Reverse Engineering und Hardware-Sicherheit. Verantwortlich für mehrere Responsible Disclosures.

OSCP+ OSCP OSWP OSWA
Zertifiziert ISO 27001ISO 9001AZAV