RFC 9700, im Januar 2025 als BCP 240 veröffentlicht, legt fest, welche Härtungsmaßnahmen für OAuth 2.0 ein MUST und welche nur ein SHOULD sind. Eine Wildcard-Redirect-URI, die in der Konsole eines Identity Providers stehen geblieben ist, schließt der RFC aus, und sauberer Client-Code gleicht das nicht aus. Der RFC aktualisiert RFC 6749, RFC 6750 und RFC 6819 und warnt, dass seine Umsetzung die Interoperabilität mit älteren Ökosystemen beeinträchtigen kann. Dennoch empfiehlt er, so bald wie möglich umzustellen.
Die Anforderungen nach Verbindlichkeit
| Einstellung | Stufe | Position in RFC 9700 |
|---|---|---|
| Vergleich der Redirect-URI | MUST | Authorization Server verwenden exakten String-Vergleich |
| Open Redirectors | MUST NOT | Clients und Authorization Server dürfen keine bereitstellen |
| CSRF-Schutz | MUST | Clients schützen den Redirection Endpoint: PKCE, nonce oder ein einmaliges state |
| Mix-up-Abwehr, mehrere Authorization Server | REQUIRED | iss-Parameter oder gleichwertiger iss-Wert; als Fallback getrennte Redirection-URIs |
| PKCE, Public Clients | MUST | Beim Authorization Code Grant erforderlich |
| PKCE, Confidential Clients | RECOMMENDED | OpenID-Connect-Clients dürfen stattdessen nonce verwenden, mit zusätzlichen Vorkehrungen |
Durchsetzung von code_verifier | MUST | Am Token Endpoint erzwungen, sobald ein gültiger code_challenge gesendet wurde |
| PKCE-Challenge-Methode | SHOULD | Eine Methode, die den Verifier nicht preisgibt; derzeit nur S256 |
Implicit Grant (response_type=token) | SHOULD NOT | code oder einen anderen Typ verwenden, der Tokens am Token Endpoint ausstellt |
| Sender-constrained Access Tokens | SHOULD | Mutual TLS oder DPoP |
| Refresh Tokens, Public Clients | MUST | Sender-constrained oder rotiert |
Redirect-URIs: exakter Abgleich und keine Open Redirectors
Wenn der Authorization Server die redirect_uri einer Anfrage mit den registrierten Werten vergleicht, muss er einen exakten String-Vergleich verwenden. Die einzige Ausnahme ist die Portnummer bei Localhost-Redirection-URIs nativer Apps. Wildcards, Präfix-Treffer und Registrierungen nach dem Muster "beliebiger Pfad unter diesem Host" verstoßen alle gegen diese Regel.
Auch die registrierte Liste ist wichtig, denn jeder Eintrag ist ein erlaubtes Ziel für Authorization Codes. Entfernen Sie veraltete Einträge, insbesondere Hosts, die Sie nicht mehr kontrollieren, etwa eine stillgelegte Staging-Domain, die jemand anderes übernehmen könnte.
Open Redirectors sind die andere Hälfte des Problems. Ein Endpoint, der den Browser auf eine beliebige URI aus einem Query-Parameter weiterleitet, kann Authorization Codes und Access Tokens preisgeben. Der RFC verbietet es sowohl Clients als auch Authorization Servern, einen solchen Endpoint bereitzustellen. Das OWASP-Beispiel http://example.com/example.php?url=http://malicious.example.com zeigt das Problem: Der Nutzer sieht den vertrauenswürdigen Host und übersieht die Weiterleitung.
Die Lösung liefert das OWASP Cheat Sheet zu Unvalidated Redirects. Am besten ordnen Sie auf dem Server einer kurzen ID ein Ziel zu, statt eine URL entgegenzunehmen. Wenn Sie eine URL akzeptieren müssen, parsen Sie sie mit einem gepflegten Parser und vergleichen Schema, kanonischen Host und effektiven Port mit einer expliziten Allowlist. Lehnen Sie Userinfo ab und verlassen Sie sich niemals auf rohe Präfix- oder Suffix-Vergleiche.
PKCE bei jedem Client, verpflichtend bei Public Clients
Public Clients müssen PKCE verwenden. Für Confidential Clients wird es empfohlen, weil es auch Code Injection verhindert und nebenbei CSRF abwehrt. Confidential OpenID-Connect-Clients dürfen stattdessen nonce und den passenden ID-Token-Claim nutzen, aber nur mit den Vorkehrungen aus Abschnitt 4.5.3.2. Die Empfehlung gilt auch für Webanwendungen, obwohl PKCE für native Apps entworfen wurde.
- Der Challenge-Wert muss sich bei jeder Transaktion ändern. Ein konstanter Wert verfehlt den Zweck.
- Verwenden Sie
S256. RFC 9700 nennt sie derzeit die einzige Methode, die den Verifier in der Authorization Request nicht preisgibt; ein Angreifer, der diese Anfrage mitlesen kann, kann PKCE sonst brechen. RFC 7636 ergänzt, dassplainnur einen Angreifer abwehrt, der ausschließlich Responses sieht. - Der Verifier ist ein zufälliger String aus 43 bis 128 Zeichen des Unreserved-Zeichensatzes. RFC 7636 empfiehlt 32 zufällige Oktette, base64url-kodiert, was 43 Zeichen ergibt.
Der Server muss außerdem Downgrades verhindern: Eine Token-Anfrage mit code_verifier wird nur akzeptiert, wenn die Authorization Request einen code_challenge enthielt. Wer code_challenge_methods_supported in den Server-Metadaten veröffentlicht, ermöglicht es Clients, die PKCE-Unterstützung zu erkennen.
Implicit Grant, CSRF und Mix-up
Clients sollten weder response_type=token noch einen anderen Response Type verwenden, der Access Tokens in der Authorization Response zurückgibt. RFC 9700 bezeichnet diese als anfällig für Token-Leakage und Replay und stellt fest, dass es kein standardisiertes Verfahren gibt, ein so ausgestelltes Token sender-constrained zu machen. Verwenden Sie code oder einen Typ, der Tokens am Token Endpoint ausstellt, etwa code id_token.
CSRF am Redirection Endpoint erfordert PKCE (wenn der Client sich vergewissert hat, dass der Server es unterstützt), das nonce in OpenID-Connect-Flows oder einen einmaligen state-Wert, der an den User Agent gebunden ist. Wenn Ihr Client mit mehr als einem Authorization Server spricht, nutzen Sie den iss-Parameter aus RFC 9207 oder einen gleichwertigen iss-Wert, zum Beispiel den ID-Token-Claim.
Tokens: Sender-Constraining, wo immer es geht
Authorization und Resource Server sollten Access Tokens per Mutual TLS (RFC 8705) oder DPoP (RFC 9449) sender-constrained machen, sodass ein gestohlenes Token ohne das zugehörige Secret nutzlos ist. Refresh Tokens für Public Clients müssen sender-constrained oder rotiert sein, wie in Abschnitt 4.14 des RFC beschrieben.
Wo Sie anfangen
- Listen Sie für jeden Client alle registrierten Redirect-URIs auf. Entfernen Sie Wildcards, Teilpfade und Hosts, die Sie nicht mehr kontrollieren. Hängen Sie anschließend in einer echten Authorization Request einen Pfad an oder ändern Sie eine Subdomain; der Server sollte die Anfrage ablehnen.
- Suchen Sie im Client und im Authorization Server nach Redirect-Parametern wie
url,nextoderreturnUrl. Ersetzen Sie frei wählbare URLs durch eine serverseitige ID-Zuordnung oder eine Allowlist auf Basis geparster URLs. - Durchsuchen Sie Client-Code und Servereinstellungen nach
response_type=token. Stellen Sie diese Clients auf den Authorization Code Flow mit PKCE undS256um. - Testen Sie PKCE direkt. Senden Sie eine Authorization Request ohne
code_challengeund lösen Sie den Code dann mit einemcode_verifierein. Lösen Sie anschließend einen PKCE-geschützten Code ohne Verifier ein. Beides sollte am Token Endpoint scheitern; ein Token in der Antwort bedeutet, dass der Server den Test nicht besteht. - Testen Sie
state: Spielen Sie einen bereits verwendeten Wert erneut ein und reichen Sie dann einen Wert aus einer anderen Browser-Session ein; der Client muss beides ablehnen. Falls Ihr Providerisszurückgibt, manipulieren Sie den Wert und prüfen Sie, ob der Client die Antwort verwirft. ID-Token-Claims können Sie mit unserem JWT-Tool untersuchen, und wenn Sie eine externe Prüfung wünschen, kann ein Penetrationstest die Flows abdecken. - Entscheiden Sie sich bei Public Clients für Sender-Constraining oder Rotation. Wenn Sie rotieren, legen Sie in einem Test ein bereits benutztes Refresh Token zweimal vor und beobachten Sie, wie der Server reagiert. Suchen Sie diesen Versuch in den Logs des Authorization Servers, da die Ereignisnamen je nach Produkt abweichen, und richten Sie dafür einen Alarm ein.
