OAuth 2.0 güvenliği, yalnızca bir kimlik sağlayıcısında uygulama kaydı açıp istemci kimliği almak değildir. Yetkilendirme kodunun, redirect URI'nin, tarayıcı oturumunun, erişim ve yenileme tokenlarının yaşam döngüsü birlikte tasarlanmadığında çalışan bir entegrasyon aynı zamanda hesap ele geçirme, token sızıntısı veya yetki karışıklığı üretebilir.

OAuth 2.0 bir yetkilendirme çerçevesidir; kullanıcının kimliğini uygulamaya güvenilir biçimde bildirmek için OpenID Connect (OIDC) katmanı kullanılır. “OAuth ile giriş” ifadesi pratikte çoğu zaman OIDC Authorization Code Flow anlamına gelmelidir. Erişim tokenını kullanıcı kimliği kanıtı gibi kullanmak, tokenın hedef kitlesi ve amacı karıştırıldığında ciddi güvenlik hatasıdır.

Bu rehber RFC 9700 OAuth 2.0 Security Best Current Practice, RFC 7636 PKCE, OpenID Connect Core, RFC 9449 DPoP ve modern tarayıcı uygulamaları için RFC 10017 doğrultusunda güvenli bir başlangıç modeli sunar.

OAuth ve OpenID Connect rollerini ayırın

BileşenGörevGüvenlik sorumluluğu
Authorization Server / OpenID ProviderKullanıcıyı doğrular, izin toplar ve token üretirİstemciyi, redirect URI'yi, PKCE'yi, kapsamı ve token politikasını doğrular
Client / Relying PartyKullanıcı adına yetki ister ve sonucu işlerstate, nonce ve PKCE üretir; callback'i ve tokenları doğrular
Resource Server / APIErişim tokenıyla korunan kaynağı sunarimza, issuer, audience, süre, kapsam ve gerektiğinde DPoP/mTLS bağını doğrular
User AgentTarayıcı veya sistem tarayıcısıGüvenilir kullanıcı arayüzü ve yönlendirme kanalı sağlar; token deposu olarak görülmemelidir
Resource Owner / End-UserYetki veren kullanıcıİstenen kapsamı ve uygulamayı değerlendirir


OIDC, OAuth üzerine ID Token, UserInfo ve standart kimlik alanları ekler. ID Token istemcinin kullanıcı oturumunu kurması içindir. Access Token ise API'ye sunulur. API, ID Tokenı yetki belirteci olarak; istemci de Access Tokenı kimlik kanıtı olarak kabul etmemelidir.

Önerilen temel akış: Authorization Code + PKCE

Modern web, mobil ve masaüstü uygulamalarında temel tercih Authorization Code Flow ve PKCE olmalıdır. RFC 9700, erişim tokenını doğrudan yetkilendirme yanıtında döndüren implicit grant kullanımını önermiyor. Kod akışı tokenı URL fragmentine koymaz ve token endpointinde ek doğrulama sağlar.


  1. İstemci kriptografik rastgele bir code_verifier üretir.
  2. Verifier'ın SHA-256 özeti Base64url ile kodlanarak code_challenge oluşturulur.
  3. Yetkilendirme isteği response_type=code, code_challenge ve code_challenge_method=S256 ile gönderilir.
  4. Authorization Server kullanıcıyı doğrular ve tek kullanımlık kısa ömürlü kodu kayıtlı redirect URI'ye yollar.
  5. İstemci kodu token endpointine code_verifier ile sunar.
  6. Sunucu verifier ile başlangıçtaki challenge eşleşmeden token üretmez.



CODE TERMINAL
# Temsili yetkilendirme isteği
GET /authorize?
  response_type=code&
  client_id=web-client&
  redirect_uri=https%3A%2F%2Fapp.example%2Foauth%2Fcallback&
  scope=openid%20profile%20email&
  state=RANDOM_SESSION_BOUND_VALUE&
  nonce=RANDOM_LOGIN_VALUE&
  code_challenge=BASE64URL_SHA256_VERIFIER&
  code_challenge_method=S256


Code verifier veya gerçek tokenları günlük, örnek kod, hata ekranı ya da analitik sistemine yazmayın. Örnekteki değerler biçimi göstermek içindir; üretimde güvenli rastgelelik kaynağı kullanılmalıdır.

PKCE neyi engeller, neyi engellemez?

PKCE, saldırganın yetkilendirme kodunu ele geçirse bile başlangıçtaki verifier olmadan token almasını zorlaştırır. Mobil uygulamalarda özel URI şemasını başka uygulamanın yakalaması ve tarayıcı tabanlı istemcilerde kod enjeksiyonu gibi risklere karşı güçlü bir bağ oluşturur.

RFC 9700'a göre Authorization Server PKCE'yi desteklemeli; istemciler verifier'ı yetkilendirme isteğinde açığa çıkarmayan S256 yöntemini kullanmalıdır. Sunucu downgrade saldırısını önlemek için token isteğinde code_verifier varsa ilk istekte challenge bulunup bulunmadığını denetlemeli ve eşleşmeyi zorunlu kılmalıdır.

PKCE tek başına her şeyi çözmez. Yanlış redirect URI, kötü amaçlı SDK, tarayıcı içindeki XSS, güvensiz token depolama veya API'nin audience kontrolü yapmaması ayrı risklerdir. PKCE, client secret'ın mobil uygulama ya da SPA içine gömülmesini de güvenli hâle getirmez; dağıtılan istemci içindeki sabit sır gerçek anlamda gizli değildir.

State ve nonce aynı şey değildir

ParametreBağladığı şeyTemel amaçDoğrulama noktası
stateYetkilendirme isteğini yerel tarayıcı/uygulama oturumunaCSRF ve yanıt karışıklığını önleme, güvenli akış korelasyonuCallback alınır alınmaz, tek kullanımlı ve sabit zamanlı karşılaştırma
nonceOIDC Authentication Request'i dönen ID TokenaID Token replay ve oturum enjeksiyonuna karşı bağID Token imza/claim doğrulaması sırasında nonce claim ile karşılaştırma
code_verifierİstemci örneğini yetkilendirme kodunaKod ele geçirme ve enjeksiyona karşı kriptografik bağToken endpointinde challenge ile karşılaştırma


State içine dönüş URL'si, kullanıcı e-postası veya başka hassas veri düz metin koymayın. Sunucu tarafında rastgele bir tutacağa bağlanan oturum kaydı kullanın. Uygulama state içinde veri taşımak zorundaysa bütünlüğünü imza veya authenticated encryption ile koruyun ve açık yönlendirme üretmeyecek allowlist uygulayın.

Nonce her giriş denemesinde yeni olmalı, ilgili oturuma bağlanmalı ve ID Token içindeki nonce alanıyla eşleşmeden oturum kurulmasına izin verilmemelidir. State veya nonce değerinin yalnızca “var” olması yeterli değildir; tahmin edilemez, tek kullanımlı, süreli ve oturuma bağlı olmalıdır.

Redirect URI doğrulaması neden kritik?

Authorization Server redirect URI'yi önceden kaydedilmiş tam değerle eşleştirmelidir. Wildcard, alt dize, gevşek regex, protokol düşürme veya kullanıcı bilgisini içeren URL ayrıştırma hataları kodun saldırgan alanına gönderilmesine yol açabilir.


  • https://app.example/callback ile https://app.example.evil.test/callback aynı origin değildir.
  • Path normalizasyonu, büyük-küçük harf, yüzde kodlama ve sondaki slash davranışı kütüphaneler arasında değişebilir.
  • Açık redirect endpointi kayıtlı callback altında bulunuyorsa saldırgan kodu zincirleme yönlendirebilir.
  • Yerel geliştirme callback'leri üretim istemci kaydına eklenmemeli; ayrı client_id kullanılmalıdır.
  • Mobil uygulamalarda claimed HTTPS/universal link veya loopback redirect, RFC 8252 modeline göre değerlendirilmelidir.



İstemci tarafında callback işlendiğinde yalnızca kod ve state değil, hata yanıtları da güvenli biçimde ele alınmalıdır. Hata mesajında tüm URL'yi, kodu veya tokenı kullanıcıya ve gözlemleme sistemine yansıtmayın.

ID Token doğrulama kontrol listesi

JWT biçiminde olması ID Tokenın güvenilir olduğu anlamına gelmez. İstemci aşağıdaki kontrolleri güvenilir sağlayıcı metadata'sından aldığı anahtarlarla yapmalıdır:


  1. İmza algoritması beklenen allowlist içinde mi ve imza geçerli mi?
  2. iss tam olarak yapılandırılmış issuer ile eşleşiyor mu?
  3. aud bu istemcinin client_id değerini içeriyor mu? Birden çok audience varsa azp kuralı uygulanıyor mu?
  4. exp geçmemiş, iat ve gerekirse nbf kabul edilen saat sapmasında mı?
  5. Dönen nonce bu oturumdaki tek kullanımlık değerle eşleşiyor mu?
  6. Akış gerektiriyorsa at_hash ve c_hash gibi bağlayıcı alanlar doğrulanıyor mu?
  7. Anahtar kimliği bulunamadığında metadata ve JWKS güvenli kaynaktan yenileniyor mu; saldırgan URL'si takip edilmiyor mu?



Algoritma seçimini token başlığından körlemesine kabul etmeyin. “none” algoritmasını reddedin ve HMAC/RSA anahtar türü karışıklığına izin vermeyin. Hazır, güncel ve yaygın denetlenmiş OIDC kütüphanesi kullanmak bu kontrolleri elle yazmaktan daha güvenlidir; yine de kütüphanenin varsayılanlarını ve hangi claimleri doğruladığını test edin.

Access Tokenı API tarafında doğrulama

Resource Server her istekte tokenın yalnızca imzasına değil bağlamına bakmalıdır:


  • Güvenilir issuer ve doğru audience
  • Süre alanları ve kabul edilen saat sapması
  • İstenen işlem için gerekli scope veya authorization_details
  • Kullanıcı/istemci ayrımı ve tenant/organization bağlamı
  • Token türü ve doğrulama yöntemi; JWT veya introspection
  • DPoP ya da mTLS kullanılıyorsa sunan istemciye kriptografik bağ



Audience kontrolü yapılmadığında bir API için üretilmiş token başka API'de kabul edilebilir. Scope kontrolü yalnızca endpoint seviyesinde değil nesne ve tenant yetkisiyle birlikte uygulanmalıdır. “profile.read” kapsamı, kullanıcının başka tenanttaki tüm profilleri okuyabileceği anlamına gelmez.

Access tokenı query string ile taşımayın. URL'ler tarayıcı geçmişi, proxy, referer ve uygulama günlüklerine sızabilir. Bearer token normalde Authorization başlığında gönderilmeli ve TLS uçtan uca korunmalıdır.

Refresh token rotasyonu ve tekrar kullanım tespiti

Uzun ömürlü refresh token, ele geçirildiğinde sürekli yeni access token üretme gücü verir. RFC 9700, public client refresh tokenlarının sender-constrained olmasını veya refresh token rotation kullanmasını ister.

Rotasyonda her başarılı yenileme yeni refresh token üretir ve eskisini geçersiz kılar. Daha önce kullanılmış token yeniden görülürse aynı token ailesinin ele geçirilmiş olabileceği anlaşılır. Sistem ilgili aileyi iptal etmeli, oturumu sonlandırmalı ve olayı alarm olarak kaydetmelidir.

Yarış koşullarını hesaba katın: mobil ağ tekrarları veya paralel sekmeler meşru tokenın iki kez sunulmasına neden olabilir. Kısa bir idempotency/pencere modeli uygulanabilir; ancak eski tokenın süresiz kabulü rotasyonun güvenlik değerini yok eder.

DPoP ile çalınan tokenın tekrar kullanımını azaltma

Bearer tokenı kim ele geçirirse kullanabilir. RFC 9449 DPoP, tokenı istemcinin ürettiği bir açık/özel anahtar çiftine bağlar. İstemci her HTTP isteğinde method ve hedef URI gibi alanları içeren imzalı bir DPoP proof gönderir; API token içindeki anahtar bağıyla proof'u karşılaştırır.

DPoP kontrolüAmaç
Proof imzası ve public keyİstemcinin ilgili özel anahtara sahip olduğunu kanıtlama
htm ve htuProof'u belirli HTTP methodu ve hedef URI'ye bağlama
iat ve kabul penceresiEski proof tekrarını sınırlandırma
jti tekrar önlemeAynı proof'un yeniden kullanılmasını tespit etme
athProof'u sunulan access tokenın hashine bağlama
nonce desteğiSunucunun taze proof istemesine ve replay alanını daraltmasına yardım etme


DPoP, istemci cihaz tamamen ele geçirilmiş ve özel anahtar kullanılabiliyorsa mutlak koruma sağlamaz. Buna rağmen yalnızca tokenı gören proxy günlüğü, kötü yönlendirme veya veri sızıntısı aktörünün başka cihazdan replay yapmasını zorlaştırır. Yüksek güvenli sunucu-sunucu senaryolarında mTLS sender-constrained token da değerlendirilebilir.

Tarayıcı tabanlı uygulamalarda BFF yaklaşımı

Tarayıcı JavaScript ortamı XSS, kötü amaçlı eklenti ve tedarik zinciri riskine açıktır. RFC 10017, browser-based uygulamaların tehdit modelini ve mimari seçeneklerini açıklar. Hassas tokenları tarayıcıdan uzak tutmak için Backend for Frontend (BFF) güçlü bir yaklaşımdır:


  1. Tarayıcı yalnızca uygulamanın BFF sunucusuyla HttpOnly, Secure ve uygun SameSite cookie üzerinden oturum kurar.
  2. OAuth kod değişimi ve token saklama sunucu tarafında yapılır.
  3. BFF, API isteklerini tokenla sunucu tarafında iletir veya kontrollü bir session-based proxy sağlar.
  4. Tarayıcı JavaScript'i access veya refresh tokenı okuyamaz.



BFF de CSRF, oturum sabitleme, cookie kapsamı, CORS ve sunucu tarafı istek sahteciliği kontrolleri gerektirir. HttpOnly cookie XSS'i tamamen önlemez; saldırgan sayfa bağlamından kullanıcının oturumuyla işlem yapabilir. Bu nedenle CSP, Trusted Types, bağımlılık güvenliği ve hassas işlemlerde yeniden doğrulama katmanları birlikte kullanılmalıdır.

localStorage ve sessionStorage içindeki tokenlar sayfadaki JavaScript tarafından okunabilir. XSS olduğunda token dışarı çıkarılabilir. Bellekte tutmak kalıcılığı azaltır fakat aktif XSS sırasında koruma sağlamaz. Depolama kararı tehdit modeline göre verilmelidir.

PAR ve metadata ile yapılandırma riskini azaltma

RFC 9126 Pushed Authorization Requests (PAR), yetkilendirme parametrelerini ön kanaldaki uzun URL yerine istemcinin Authorization Server'a doğrulanmış arka kanal isteğiyle göndermesini sağlar. Tarayıcıya yalnızca kısa ömürlü request_uri gider. Bu, parametre kurcalama ve hassas istek ayrıntılarının ön kanalda açığa çıkmasını azaltabilir.

RFC 8414 Authorization Server Metadata ve OIDC Discovery, endpoint ve yeteneklerin standart biçimde yayımlanmasını sağlar. İstemci metadata URL'sini kullanıcı girdisinden kurmamalı; güvenilir issuer allowlist'i kullanmalı, HTTPS ve issuer eşleşmesini doğrulamalıdır. Dinamik discovery yanlış uygulanırsa SSRF ve kötü amaçlı endpoint yönlendirmesi üretebilir.

Client secret ve istemci kimlik doğrulama

SPA, mobil ve dağıtılan masaüstü uygulamasına gömülen client secret gizli değildir. Bu istemciler public client olarak kayıt edilmeli ve PKCE kullanmalıdır. Confidential client sırları ise kaynak kod, container image, CI logu veya düz metin yapılandırmada tutulmamalıdır.

RFC 9700 mümkün olduğunda asimetrik istemci kimlik doğrulamayı önerir. private_key_jwt veya mTLS gibi yöntemler Authorization Server'ın paylaşılan simetrik sır saklama ihtiyacını azaltabilir. Anahtarlar donanım veya yönetilen secret/key kasasında tutulmalı; kid, rotasyon, süre ve iptal süreçleri otomatikleştirilmelidir.

Logout, iptal ve oturum sonlandırma

Uygulamada “çıkış” yalnızca yerel cookie'yi silmekle bitmez. Risk ve kullanıcı beklentisine göre:


  • Yerel oturum cookie'si sunucu tarafında geçersiz kılınmalı.
  • Refresh token RFC 7009 revocation endpointiyle iptal edilmeli veya token ailesi sonlandırılmalı.
  • OIDC sağlayıcı oturumunu kapatmak gerekip gerekmediği açıkça tasarlanmalı; tek oturum açma kullanan diğer uygulamalar etkilenebilir.
  • Back-channel logout veya olay tabanlı oturum iptali desteği değerlendirilmeli.
  • Parola değişimi, hesap kapatma ve yönetici müdahalesi tüm aktif oturum/token ailelerini etkileyebilmelidir.



Kısa ömürlü access token iptal maliyetini azaltır; ancak tek başına refresh token sızıntısını çözmez. Güvenlik olayı sırasında kullanıcı, client, cihaz ve token ailesi seviyesinde seçici iptal yapılabilmelidir.

Günlükleme ve tehdit algılama

Tokenın kendisini kaydetmeden aşağıdaki güvenlik olaylarını ilişkilendirin:


  • Başarısız state, nonce, PKCE veya redirect URI doğrulaması
  • Aynı authorization code'un ikinci kez kullanılması
  • Refresh token reuse tespiti ve aile iptali
  • Beklenmeyen issuer, audience, azp veya imza algoritması
  • Aynı oturum için kısa sürede farklı ülke/ASN ve cihaz sinyalleri
  • Yeni client kaydı, redirect URI değişikliği ve secret/anahtar rotasyonu
  • Olağan dışı kapsam talebi ve yüksek riskli consent
  • DPoP jti tekrarı, htm/htu uyuşmazlığı ve nonce hatası



Günlüklerde access token, refresh token, authorization code, client secret, session cookie veya tam callback URL'si bulunmamalıdır. Korelasyon için geri döndürülemez hash, olay kimliği ve kullanıcı/istemci takma kimliği kullanılabilir. Gerekli saklama süresi ve erişim yetkisi veri minimizasyonuyla sınırlandırılmalıdır.

Test senaryoları


  1. Kayıt dışı redirect URI, alt alan adı benzeri ve yüzde kodlanmış varyantları reddediliyor mu?
  2. State eksik, yanlış, süresi geçmiş veya ikinci kez kullanıldığında akış duruyor mu?
  3. Nonce başka oturumdan replay edildiğinde ID Token reddediliyor mu?
  4. PKCE olmadan veya plain yöntemiyle istek kabul ediliyor mu; downgrade mümkün mü?
  5. Authorization code ikinci kez kullanıldığında token üretiliyor mu?
  6. ID Token yanlış issuer, audience, algoritma, kid veya süresi geçmiş claimlerle reddediliyor mu?
  7. Access token yanlış API audience'ında ve yetersiz scope ile reddediliyor mu?
  8. Refresh token reuse bütün aileyi iptal ediyor ve alarm üretiyor mu?
  9. DPoP proof farklı method, URI, token veya jti ile replay edildiğinde reddediliyor mu?
  10. Hata sayfası ve telemetry token ya da callback URL'si sızdırıyor mu?



Bu testleri yalnızca bir kez penetrasyon testi sırasında değil, kimlik sağlayıcı, proxy, SDK ve uygulama sürümleri değiştikçe otomatik entegrasyon testlerinde çalıştırın.

Sık yapılan hatalar


  • OAuth access tokenını kullanıcı kimliği kanıtı olarak kullanmak
  • Implicit grant veya tokenı URL'de taşıyan eski akışta kalmak
  • PKCE'yi yalnızca mobil uygulamalara gerekli sanmak
  • State ile nonce'u birbirinin yerine kullanmak veya değerleri oturuma bağlamamak
  • Wildcard redirect URI ve açık yönlendirme bırakmak
  • SPA veya mobil uygulamaya client secret gömmek
  • JWT imzasını doğrulayıp issuer, audience, süre ve kapsamı kontrol etmemek
  • Refresh tokenı rotasyonsuz ve uzun ömürlü tutmak
  • Tokenları localStorage, URL, hata izleme ve proxy günlüklerinde açığa çıkarmak
  • Discovery/metadata adresini kullanıcı girdisinden üretip SSRF'e yol açmak
  • Çıkışta yalnızca tarayıcı cookie'sini silmek



Üretim kontrol listesi


  1. Authorization Code Flow + PKCE S256 kullanın; implicit grantı kaldırın.
  2. Her istek için rastgele, tek kullanımlı ve oturuma bağlı state ile OIDC nonce üretin.
  3. Redirect URI'leri tam eşleştirin; wildcard ve açık redirect kullanmayın.
  4. ID Token için imza, iss, aud/azp, exp/iat ve nonce kontrollerini zorunlu kılın.
  5. API'de issuer, audience, scope ve nesne/tenant yetkisini birlikte doğrulayın.
  6. Public client refresh tokenlarında rotasyon veya sender constraint uygulayın.
  7. Yüksek riskli akışlarda DPoP veya mTLS değerlendirin.
  8. Tarayıcı uygulamalarında BFF ile tokenları JavaScript'ten uzak tutun.
  9. Metadata/discovery kaynağını allowlist ile sınırlayın ve issuer eşleşmesini doğrulayın.
  10. Token ve kodları günlüklerden temizleyin; güvenlik olaylarını tokenın kendisi olmadan izleyin.
  11. Revocation, logout ve olay anı token ailesi iptalini test edin.
  12. Kimlik SDK'sı ve Authorization Server güncellemelerini düzenli güvenlik testine bağlayın.



Sonuç

Güvenli OAuth 2.0 ve OpenID Connect entegrasyonu, Authorization Code + PKCE seçimiyle başlar; fakat state, nonce, sıkı redirect URI, ID Token claim doğrulaması, API audience/scope kontrolü ve refresh token yaşam döngüsü olmadan tamamlanmaz. Bearer token replay riskinin yüksek olduğu ortamlarda DPoP veya mTLS ile tokenı sunan istemciye bağlamak savunmayı güçlendirir.

Tarayıcı tabanlı uygulamalarda BFF, hassas tokenları JavaScript ortamından uzaklaştırır. En önemli operasyonel ilke ise tokenları sır olarak ele almak, günlüklememek ve her doğrulama başarısızlığını izlenebilir bir güvenlik olayı hâline getirmektir.

Kaynaklar

TR Siber Ekibi Yazar · X
Kaynak bağlantısı ← Ana sayfaya dön