RFC 9700, in januari 2025 gepubliceerd als BCP 240, geeft aan welke hardeningmaatregelen voor OAuth 2.0 MUST zijn en welke slechts SHOULD. Een wildcard redirect URI die in de console van een identity provider is blijven staan, is precies het soort instelling dat de RFC uitsluit, en schone clientcode maakt dat niet goed. De RFC werkt RFC 6749, RFC 6750 en RFC 6819 bij en waarschuwt dat het volgen ervan de interoperabiliteit met oudere ecosystemen kan verstoren. Toch adviseert de RFC om zo snel als haalbaar te upgraden.
De eisen, op sterkte
| Instelling | Niveau | Standpunt RFC 9700 |
|---|---|---|
| Vergelijking van redirect URI's | MUST | Authorization servers gebruiken exacte stringvergelijking |
| Open redirectors | MUST NOT | Clients en authorization servers mogen ze niet blootstellen |
| CSRF-bescherming | MUST | Clients beschermen het redirection endpoint: PKCE, nonce of een eenmalige state |
| Mix-up-bescherming, meerdere authorization servers | REQUIRED | iss-parameter of gelijkwaardige iss-waarde; aparte redirection URI's als terugvaloptie |
| PKCE, public clients | MUST | Verplicht bij de authorization code grant |
| PKCE, confidential clients | RECOMMENDED | OpenID Connect-clients MAY in plaats daarvan nonce gebruiken, met extra voorzorgsmaatregelen |
Afdwingen van code_verifier | MUST | Wordt afgedwongen bij het token endpoint zodra een geldige code_challenge is verstuurd |
| PKCE challenge method | SHOULD | Een methode die de verifier niet blootlegt; momenteel alleen S256 |
Implicit grant (response_type=token) | SHOULD NOT | Gebruik code of een ander type dat tokens uitgeeft bij het token endpoint |
| Sender-constrained access tokens | SHOULD | Mutual TLS of DPoP |
| Refresh tokens, public clients | MUST | Sender-constrained of geroteerd |
Redirect URI's: exacte match en geen open redirectors
Wanneer de authorization server de redirect_uri in een request vergelijkt met de geregistreerde waarden, moet hij exacte stringvergelijking gebruiken. De enige uitzondering is het poortnummer in localhost-redirection-URI's van native apps. Wildcards, prefixmatches en registraties als "elk pad onder deze host" voldoen allemaal niet aan deze regel.
Ook de geregistreerde lijst zelf telt, omdat elke vermelding een toegestaan doel is voor authorization codes. Verwijder verouderde vermeldingen, vooral van hosts die u niet meer beheert, zoals een uit gebruik genomen staging-domein dat iemand anders kan overnemen.
Open redirectors vormen de andere helft van het probleem. Een endpoint dat de browser doorstuurt naar een willekeurige URI uit een queryparameter kan authorization codes en access tokens laten lekken, en volgens de RFC mogen noch clients noch authorization servers er een blootstellen. Het OWASP-voorbeeld http://example.com/example.php?url=http://malicious.example.com laat het probleem zien: de gebruiker ziet de vertrouwde host en mist de redirect.
De OWASP cheat sheet over unvalidated redirects geeft de oplossing. Het beste is om op de server een korte ID aan een doel te koppelen in plaats van een URL te accepteren. Moet u toch een URL accepteren, parseer die dan met een onderhouden parser en vergelijk scheme, canonieke host en effectieve poort met een expliciete allowlist. Weiger userinfo en match nooit op ruwe prefixen of suffixen.
PKCE bij elke client, verplicht bij public clients
Public clients moeten PKCE gebruiken. Voor confidential clients is het aanbevolen, omdat het ook code injection tegengaat en daarnaast CSRF. Confidential OpenID Connect-clients mogen in plaats daarvan nonce en de bijbehorende ID Token-claim gebruiken, maar alleen met de voorzorgsmaatregelen uit sectie 4.5.3.2. Het advies geldt ook voor webapplicaties, hoewel PKCE voor native apps is ontworpen.
- De challenge-waarde moet per transactie veranderen. Een constante waarde ondermijnt het doel.
- Gebruik
S256. RFC 9700 noemt dit momenteel de enige methode die de verifier niet blootlegt in de authorization request; een aanvaller die dat request kan lezen, kan PKCE anders breken. RFC 7636 voegt toe datplainalleen beschermt tegen een aanvaller die uitsluitend responses ziet. - De verifier is een willekeurige string van 43 tot 128 tekens uit de set unreserved characters. RFC 7636 beveelt 32 willekeurige octets aan, base64url-gecodeerd, wat 43 tekens oplevert.
De server moet ook een downgrade blokkeren: een tokenrequest met een code_verifier wordt alleen geaccepteerd als het authorization request een code_challenge bevatte. Door code_challenge_methods_supported in de servermetadata te publiceren kunnen clients detecteren dat PKCE wordt ondersteund.
Implicit grant, CSRF en mix-up
Clients zouden response_type=token of een ander response type dat access tokens in de authorization response teruggeeft niet moeten gebruiken. RFC 9700 noemt deze kwetsbaar voor tokenlekkage en replay en merkt op dat er geen gestandaardiseerde methode bestaat om een op die manier uitgegeven token sender-constrained te maken. Gebruik code, of een type dat tokens uitgeeft bij het token endpoint, zoals code id_token.
CSRF op het redirection endpoint vraagt om PKCE (als de client heeft vastgesteld dat de server dit ondersteunt), de nonce in OpenID Connect-flows, of een eenmalige state-waarde die aan de user agent is gebonden. Als uw client met meer dan één authorization server communiceert, gebruik dan de iss-parameter uit RFC 9207 of een gelijkwaardige iss-waarde, zoals de ID Token-claim.
Tokens: maak ze sender-constrained waar het kan
Authorization servers en resource servers zouden access tokens sender-constrained moeten maken met mutual TLS (RFC 8705) of DPoP (RFC 9449), zodat een gestolen token waardeloos is zonder het bijbehorende geheim. Refresh tokens voor public clients moeten sender-constrained of geroteerd zijn, zoals beschreven in sectie 4.14 van de RFC.
Waar u kunt beginnen
- Maak een lijst van alle geregistreerde redirect URI's van elke client. Verwijder wildcards, gedeeltelijke paden en hosts die u niet meer beheert. Voeg daarna in een live authorization request een pad toe of wijzig een subdomein; de server hoort dat te weigeren.
- Zoek op de client en de authorization server naar redirectparameters zoals
url,nextofreturnUrl. Vervang vrije URL's door een ID-mapping op de server of een allowlist op basis van geparseerde URL's. - Zoek in clientcode en serverinstellingen naar
response_type=token. Verplaats die clients naar de authorization code flow met PKCE viaS256. - Test PKCE rechtstreeks. Stuur een authorization request zonder
code_challengeen wissel de code daarna in met eencode_verifier. Wissel vervolgens een met PKCE beschermde code in zonder de verifier. Beide pogingen moeten mislukken bij het token endpoint; een token in de response betekent dat de server de test niet doorstaat. - Test
state: speel een al gebruikte waarde opnieuw af en dien daarna een waarde in vanuit een andere browsersessie; de client moet beide afwijzen. Als uw providerissteruggeeft, manipuleer die waarde dan en controleer dat de client de response afwijst. Inspecteer ID Token-claims met onze JWT-tool, en als u een externe beoordeling wilt, kan een penetratietest de flows afdekken. - Kies voor public clients tussen sender-constraining en rotatie. Als u roteert, presenteer dan in een test een al gebruikt refresh token twee keer en kijk wat de server doet. Zoek die poging op in de logs van de authorization server, want de namen van events verschillen per product, en stel er een alert voor in.
