RFC 9700, Ocak 2025'te BCP 240 olarak yayımlandı ve OAuth 2.0 sıkılaştırma maddelerinden hangilerinin MUST, hangilerinin yalnızca SHOULD olduğunu belirliyor. Kimlik sağlayıcı konsolunda unutulmuş bir wildcard redirect URI, RFC'nin yasakladığı türden bir ayardır ve temiz istemci kodu bunu telafi etmez. RFC; RFC 6749, RFC 6750 ve RFC 6819'u günceller, kendisini uygulamanın eski ekosistemlerle birlikte çalışabilirliği bozabileceği konusunda uyarır. Yine de mümkün olan en kısa sürede yükseltme yapılmasını önerir.
Gereksinimler, güçlerine göre
| Ayar | Seviye | RFC 9700'ün tutumu |
|---|---|---|
| Redirect URI karşılaştırması | MUST | Yetkilendirme sunucuları tam dize eşleşmesi (exact string matching) kullanır |
| Open redirector'lar | MUST NOT | İstemciler ve yetkilendirme sunucuları bunları açıkta bırakmamalıdır |
| CSRF koruması | MUST | İstemciler redirection endpoint'ini korur: PKCE, nonce veya tek kullanımlık state |
| Mix-up savunması, birden fazla yetkilendirme sunucusu | REQUIRED | iss parametresi veya eşdeğer bir iss değeri; yedek olarak ayrı redirection URI'leri |
| PKCE, public client'lar | MUST | Authorization code grant üzerinde zorunlu |
| PKCE, confidential client'lar | RECOMMENDED | OpenID Connect istemcileri, ek önlemlerle nonce kullanabilir (MAY) |
code_verifier zorunluluğu | MUST | Geçerli bir code_challenge gönderildiğinde token endpoint'inde zorunlu tutulur |
| PKCE challenge yöntemi | SHOULD | Verifier'ı açığa çıkarmayan bir yöntem; şu anda yalnızca S256 |
Implicit grant (response_type=token) | SHOULD NOT | code veya token'ları token endpoint'inde veren başka bir tür kullanın |
| Sender-constrained access token'lar | SHOULD | Mutual TLS veya DPoP |
| Refresh token'lar, public client'lar | MUST | Sender-constrained veya rotasyonlu |
Redirect URI'ler: tam eşleşme ve open redirector yok
Yetkilendirme sunucusu, istekteki redirect_uri değerini kayıtlı değerlerle karşılaştırırken tam dize eşleşmesi kullanmak zorundadır. Tek istisna, native uygulamaların localhost redirection URI'lerindeki port numarasıdır. Wildcard'lar, önek eşleşmeleri ve "bu host altındaki herhangi bir yol" şeklindeki kayıtların tamamı bu kuralı ihlal eder.
Kayıtlı liste de önemlidir, çünkü her giriş authorization code'lar için izin verilmiş bir hedeftir. Eskimiş girişleri kaldırın; özellikle artık kontrol etmediğiniz host'lara, örneğin kullanımdan kaldırılmış ve başkasının devralabileceği bir staging alan adına ait kayıtlara dikkat edin.
Open redirector'lar işin diğer yarısıdır. Tarayıcıyı bir sorgu parametresinden gelen rastgele bir URI'ye yönlendiren bir endpoint, authorization code'ları ve access token'ları sızdırabilir; RFC, ne istemcilerin ne de yetkilendirme sunucularının böyle bir endpoint barındırmaması gerektiğini söyler. OWASP'ın http://example.com/example.php?url=http://malicious.example.com örneği sorunu gösterir: kullanıcı güvendiği host'u görür, yönlendirmeyi fark etmez.
Çözümü unvalidated redirect'ler üzerine OWASP cheat sheet'i verir. En iyisi, URL almak yerine sunucu tarafında kısa bir ID'yi bir hedefe eşlemektir. Bir URL kabul etmek zorundaysanız, bakımı yapılan bir parser ile ayrıştırın; scheme, kanonik host ve etkin portu açık bir allowlist ile karşılaştırın. Userinfo içeren değerleri reddedin ve ham önek ya da sonek üzerinden asla eşleştirme yapmayın.
Her istemcide PKCE, public olanlarda zorunlu
Public client'lar PKCE kullanmak zorundadır. Confidential client'lar için tavsiye edilir, çünkü PKCE code injection'ı da engeller ve yan etki olarak CSRF'i de durdurur. Confidential OpenID Connect istemcileri bunun yerine nonce ve eşleşen ID Token claim'ini kullanabilir, ancak yalnızca Bölüm 4.5.3.2'deki önlemlerle. PKCE native uygulamalar için tasarlanmış olsa da bu tavsiye web uygulamaları için de geçerlidir.
- Challenge değeri her işlemde değişmelidir. Sabit bir değer amacı boşa çıkarır.
S256kullanın. RFC 9700, bunu yetkilendirme isteğinde verifier'ı açığa çıkarmayan, şu an için tek yöntem olarak niteler; bu isteği okuyabilen bir saldırgan aksi halde PKCE'yi kırabilir. RFC 7636 ayrıcaplainyönteminin yalnızca sadece yanıtları gören bir saldırganı etkisiz kıldığını ekler.- Verifier, unreserved karakter kümesinden seçilmiş 43 ile 128 karakter uzunluğunda rastgele bir dizedir. RFC 7636, base64url ile kodlanmış 32 rastgele oktet önerir; bu da 43 karakter eder.
Sunucu ayrıca downgrade'i engellemelidir: code_verifier içeren bir token isteği, yalnızca yetkilendirme isteği bir code_challenge içeriyorsa kabul edilir. Sunucu metadata'sında code_challenge_methods_supported yayımlamak, istemcilerin PKCE desteğini tespit etmesini sağlar.
Implicit grant, CSRF ve mix-up
İstemciler response_type=token veya yetkilendirme yanıtında access token döndüren herhangi bir response type kullanmamalıdır. RFC 9700 bunları token sızıntısına ve replay'e açık olarak niteler ve bu şekilde verilen bir token'ı sender-constrain etmek için standartlaştırılmış bir yöntem bulunmadığını belirtir. code ya da token'ları token endpoint'inde veren bir tür kullanın; örneğin code id_token.
Redirection endpoint'indeki CSRF için PKCE (istemci sunucunun bunu desteklediğini doğruladıysa), OpenID Connect akışlarında nonce veya kullanıcı aracısına (user agent) bağlı, tek kullanımlık bir state değeri gerekir. İstemciniz birden fazla yetkilendirme sunucusuyla konuşuyorsa RFC 9207'deki iss parametresini ya da ID Token claim'i gibi eşdeğer bir iss değerini kullanın.
Token'lar: mümkün olan yerde sender-constrain edin
Yetkilendirme ve kaynak sunucuları, çalınan bir token eşleşen sır olmadan işe yaramasın diye access token'ları mutual TLS (RFC 8705) veya DPoP (RFC 9449) ile sender-constrain etmelidir. Public client'ların refresh token'ları, RFC'nin Bölüm 4.14'ünde anlatıldığı gibi sender-constrained veya rotasyonlu olmak zorundadır.
Nereden başlamalı
- Her istemci için kayıtlı tüm redirect URI'leri listeleyin. Wildcard'ları, kısmi yolları ve artık kontrol etmediğiniz host'ları kaldırın. Ardından canlı bir yetkilendirme isteğinde bir yol ekleyin veya bir alt alan adını değiştirin; sunucu bunu reddetmelidir.
- İstemcide ve yetkilendirme sunucusunda
url,nextveyareturnUrlgibi yönlendirme parametrelerini arayın. Serbest biçimli URL'leri sunucu tarafında ID eşlemesi veya ayrıştırılmış URL allowlist'i ile değiştirin. - İstemci kodunda ve sunucu ayarlarında
response_type=tokenifadesini arayın. Bu istemcileriS256ile PKCE kullanan authorization code akışına taşıyın. - PKCE'yi doğrudan test edin.
code_challengeolmadan bir yetkilendirme isteği gönderin, ardından code'u bircode_verifierile kullanın. Sonra PKCE korumalı bir code'u verifier olmadan kullanmayı deneyin. İkisi de token endpoint'inde başarısız olmalıdır; yanıtta bir token görüyorsanız sunucu testi geçememiş demektir. statedeğerini test edin: kullanılmış bir değeri tekrar gönderin, ardından başka bir tarayıcı oturumundan alınmış bir değer gönderin; istemci ikisini de reddetmelidir. Sağlayıcınızissdöndürüyorsa onu değiştirin ve istemcinin yanıtı reddettiğini doğrulayın. ID Token claim'lerini JWT aracımızla inceleyin; dış bir değerlendirme isterseniz sızma testi bu akışları kapsayabilir.- Public client'lar için sender-constraining veya rotasyon seçin. Rotasyon uyguluyorsanız, kullanılmış bir refresh token'ı testte iki kez sunun ve sunucunun ne yaptığına bakın. Olay adları ürüne göre değiştiği için bu denemeyi yetkilendirme sunucusu loglarında bulun ve bunun için alarm tanımlayın.
