OAuth’un Temel Prensipleri

OAuth, açık yetkilendirme protokolü olarak tanımlanır ve üçüncü taraf uygulamaların sınırlı erişim elde etmesi için kullanıcı kaynaklarına izin verir. Bu protokol, kaynak sahibi, istemci ve yetkilendirme sunucusu gibi net roller tanımlar. Bu ayrım, kullanıcı kimlik bilgilerinin istemci uygulamasıyla paylaşılması gerekliliğini ortadan kaldırarak güvenliği önemli ölçüde artırır.

Protokolün temelinde yatan prensip, erişim için izin vermek yerine, erişim yetkisini temsil eden bir belirteç (token) vermektir. Bu belirteç, kullanıcının şifresini açığa çıkarmadan belirli kaynaklara ve belirli bir süre için erişim sağlar. Örneğin, bir sosyal medya uygulamasının kullanıcının e-posta hesabındaki kişileri okumasına izin vermesi istenebilir. Bu durumda, OAuth kullanıcıya, sadece kişileri okuma izni olan bir belirteç verir ve bu, uygulamanın şifreler veya diğer izinler dahil olmak üzere hesbın tam kontrolünü ele geçirmesini engeller. Güvenlik katmanı, yetkilendirme ve kimlik doğrulamanın ayrılmasıdır.

  • Kaynak Sahibi (Resource Owner): Hesap sahibi, yani kaynaklara erişim izni veren kullanıcı.
  • İstemci (Client): Kaynak sahibi adına korunan kaynaklara erişmek isteyen uygulama.
  • Kaynak Sunucusu (Resource Server): Korumalı kaynakları barındıran ve erişim belirteçlerini kabul eden sunucu (API).
  • Yetkilendirme Sunucusu (Authorization Server): Kaynak sahibinin kimliğini doğrulayan ve istemciye erişim belirteçleri veren sunucu.

JWT Yapısı ve İşleyişi

JSON Web Token (JWT), taraflar arasında güvenli bilgi aktarımı için kompakt ve kendi kendini açıklayan bir yöntem sunar. Bir JWT, noktalarla ayrılmış üç bölümden oluşur: Header (Başlık), Payload (Yük) ve Signature (İmza). Bu yapı, token'ın bütünlüğünü ve kaynağını doğrulamayı mümkün kılar. JWT'ler, özellikle dağıtık ve mikroservis mimarilerinde oturum durumunu sunucuda saklamaya gerek kalmadan kimlik bilgilerini iletmek için yaygın olarak kullanılır.

Header kısmı genellikle token'ın türünü (JWT) ve kullanılan imzalama algoritmasını (örneğin HMAC SHA256 veya RSA) belirtir. Payload, talepleri (claims) içerir; bunlar token ile ilgili olan ve kullanıcı hakkında ek veriler taşıyan ifadelerdir. İmza ise, header ve payload'ın kodlanmış hallerini, bir gizli anahtar (secret) veya özel anahtar (private key) kullanarak imzalar. Bu imza, mesajın yolda değiştirilmediğini ve güvenilir bir kaynaktan geldiğini garanti eder.

JWT'nin gücü, kendi kendine yeten ve durumsuz olmasından gelir. Alıcı taraf, token'ı doğrulamak için sadece doğru imzalama anahtarına ve algoritmaya ihtiyaç duyar; token'ın geçerliliğini kontrol etmek için veritabanı sorgusu yapması gerekmez. Bu, ölçeklenebilirliği büyük ölçüde artırır. Ancak, token çalındığında süresi dolana kadar geçersiz kılınamayacağı için kısa geçerlilik süreleri ve güvenli depolama yöntemleri kritik önem taşır.


// Örnek JWT Oluşturma ve Doğrulama (Node.js, jsonwebtoken kütüphanesi ile)
const jwt = require('jsonwebtoken');

// Bir JWT oluşturma
const payload = { userId: 12345, role: 'admin' };
const secretKey = 'your-256-bit-secret';
const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });
console.log('Oluşturulan JWT:', token);

// Bir JWT'yi doğrulama ve decode etme
try {
    const decoded = jwt.verify(token, secretKey);
    console.log('Doğrulanan Payload:', decoded);
} catch (err) {
    console.error('Token geçersiz veya süresi dolmuş:', err.message);
}
  • Header: {"alg": "HS256", "typ": "JWT"} -> Base64Url ile kodlanır.
  • Payload: {"sub": "1234567890", "name": "John Doe", "iat": 1516239022} -> Kayıtlı, genel ve özel talepler içerir.
  • Signature: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) ile oluşturulur.

Yetkilendirme Akışları

OAuth 2.0 çerçevesi, farklı istemci türleri ve güven düzeyleri için tasarlanmış çeşitli yetkilendirme akışları (grant types) tanımlar. Bu akışlar, erişim belirtecinin nasıl elde edileceğini belirleyen temel protokollerdir. Authorization Code akışı, sunucu taraflı web uygulamaları için en güvenli ve yaygın kabul gören yöntemdir. Bu akış, istemcinin kullanıcıyı bir yetkilendirme sunucusuna yönlendirmesiyle başlar ve kullanıcı iznini aldıktan sonra istemci, bir 'authorization code' alır, ardından bu kodu arka uçta bir erişim belirteciyle takas eder.

Implicit akış, istemcinin doğrudan tarayıcıdan erişim belirteci aldığı daha basit bir yöntemdi, ancak güvenlik açıkları nedeniyle modern en iyi uygulamalarda artık önerilmemektedir. Bunun yerine, tek sayfalık uygulamalar (SPA'lar) için Authorization Code with PKCE (Proof Key for Code Exchange) akışı kullanılır. Bu akış, yetkilendirme kodu değişimini güvence altına almak için bir kod mücadelesi (code challenge) ekleyerek Implicit akışın zayıflıklarını giderir. PKCE, yetkilendirme kodunun ele geçirilmesi saldırılarını etkisiz hale getirir. Diğer akışlar arasında kaynak sahibi kimlik bilgileri (şifre) ve istemci kimlik bilgileri akışı bulunur; bunlar daha yüksek güven gerektiren durumlar için ayrılmıştır.

Akış seçimi, uygulamanın türüne ve güvenlik gereksinimlerine bağlıdır. Mobil uygulamalar, genellikle hem güvenli hem de kullanıcı deneyimini koruyan PKCE ile birlikte Authorization Code akışını kullanır. Bu akışların ortak amacı, kullanıcının kimlik bilgilerini asla istemci uygulamasına maruz bırakmadan güvenli bir şekilde yetkilendirme sağlamaktır. Her akış, OAuth protokolünün farklı bileşenleri arasında belirli bir mesaj dizisini tanımlar ve bu diziler, güvenlik ve kullanılabilirlik dengesini sağlamak üzere optimize edilmiştir.

Güvenlik ve Doğrulama Mekanizmaları

OAuth ve JWT'nin güçlü bir şekilde bir arada kullanılması, kapsamlı güvenlik ve doğrulama mekanizmalarının uygulanmasını gerektirir. Bu mekanizmaların ilk ve en önemli ayağı, belirteçlerin güvenli bir şekilde taşınması ve saklanmasıdır. Erişim belirteçleri, her zaman HTTPS üzerinden iletilmeli ve istemci tarafında, JavaScript erişimine karşı korumalı alanlarda (HTTP-only cookies veya güvenli depolama) saklanmalıdır. Ayrıca, belirteçlerin kapsamı (scope) mümkün olan en dar yetki ilkesine (principle of least privilege) göre sınırlandırılmalıdır.

JWT doğrulaması, imzanın geçerliliğinin ve token süresinin kontrol edilmesinin ötesine geçmelidir. Token'ın iptal edilmesi (revocation), JWT'nin durumsuz doğası nedeniyle zorlu bir problemdir. Bu zorluğun üstesinden gelmek için genellikle kısa süreli erişim belirteçleri (access tokens) ve daha uzun süreli, ancak iptal edilebilir yenileme belirteçleri (refresh tokens) kullanılır. Yenileme belirteci bir veritabanında (veya belirteç karalama listesinde) saklanabilir ve iptal edilebilir, böylece güvenliği tehlikeye giren bir oturum sonlandırılabilir. Erişim belirteci süresi dolduğunda istemci, bu yenileme belirteci ile yeni bir erişim belirteci ister.

Diğer kritik güvenlik önlemleri arasında, JWT'nin payload'ında yer alan taleplerin (claims) dikkatli bir şekilde doğrulanması yer alır. İssuer (`iss`), Audience (`aud`) ve Subject (`sub`) gibi standart taleplerin, beklenen değerlerle eşleştiği kontrol edilmelidir. Özellikle `alg` başlığı güvenilir bir kaynaktan gelen değerle sabitlenmeli, "alg: none" gibi imza atlama saldırılarına karşı koruma sağlanmalıdır. Ayrıca, CSRF (Cross-Site Request Forgery) ve XSS (Cross-Site Scripting) saldırılarına karşı ek önlemler alınmalıdır.

Uygulama, her kullanıcı oturumu için benzersiz ve tahmin edilemez belirteçler üretmelidir. Kısa belirteç ömürleri, saldırı penceresini daraltır. Ayrıca, tüm OAuth yönlendirmeleri, kayıtlı yönlendirme URI'leri (redirect URIs) ile karşılaştırılarak doğrulanmalıdır. Bu, yetkilendirme kodlarının veya belirteçlerin farklı ve kötü niyetli bir siteye yönlendirilmesini önler. Dinamik istemci kaydı gibi gelişmiş senaryolarda, istemci kimlik doğrulaması ekstra bir güvenlik katmanı sağlar.

  • Belirteç İptali: Yenileme belirteçleri veritabanı aracılığıyla iptal edilebilir. Erişim belirteçleri için kısa TTL ve karalama listeleri kullanılabilir.
  • Kapsam Doğrulaması: API, gelen JWT'deki `scope` talebini kontrol etmeli ve istenen kaynağa/operasyona erişim izni olup olmadığını doğrulamalıdır.
  • Anahtar Yönetimi: JWT imzalamada kullanılan simetrik (secret) veya asimetrik (public/private key) anahtarlar güvenli bir şekilde saklanmalı ve düzenli olarak döndürülmelidir.
  • Saldırı Tespiti: Yanlış imza, sürsi dolmuş belirteç veya geçersiz talep nedeniyle başarısız olan çok sayıda istek, otomatik saldırı tespit sistemleri ile izlenmelidir.

Modern Uygulama Mimarisinde Entegrasyon

Mikroservis mimarileri ve API tabanlı sistemlerin yükselişi, OAuth 2.0 ve JWT'yi kimlik yönetiminin merkezine yerleştirmiştir. Bu ortamlarda, birçok bağımsız servis arasında güvenilir ve ölçeklenebilir bir yetkilendirme mekanizması gereklidir. Burada, bir Merkezi Kimlik Sağlayıcı (Identity Provider - IdP) veya yetkilendirme sunucusu, tüm uygulamalar için tek kimlik doğrulama noktası haline gelir. Diğer tüm servisler (API ağ geçitleri, mikroservisler), gelen isteklerdeki JWT erişim belirteçlerini doğrulayarak kaynak sunucusu rolünü üstlenir. Bu model, kimlik doğrulama mantığının merkezileştirilmesini sağlar, böylece her servis bu karmaşıklığı kendi içinde barındırmak zorunda kalmaz.

API Gateway'ler, bu mimaride kritik bir rol oynar. Tüm gelen istemci istekleri, ilk olarak API Gateway tarafından karşılanır. Gateway, isteğin Authorization başlığındaki JWT'yi alır, imzasını ve süresini doğrular. Doğrulama başarılı olduktan sonra, isteği ilgili arka uç mikroservisine iletir. Bu süreç, backend-for-frontend (BFF) deseni ile daha da geliştirilebilir; burada her istemci türü (web, mobil) için özelleştirilmiş bir BFF katmanı, OAuth akışlarını ve belirteç yönetimini yürüterek istemcinin karmaşıklığını azaltır. Ayrıca, JWT'nin payload'ı, kullanıcı rolü, departmanı veya diğer yetkilendirme kararları için gerekli özel taleplerle zenginleştirilebilir.

Tek sayfalık uygulamalar (SPA'lar) ve mobil uygulamalar gibi modern istemciler, bu mimaride özel dikkat gerektirir. Bu istemciler, güvenli belirteç depolama konusunda sınırlamalara sahiptir ve sunucu taraflı web uygulamalarına kıyasla daha savunmasız olabilir. Bu nedenle, bu tür istemciler için Authorization Code with PKCE akışı şarttır. Başarılı bir kimlik doğrulamanın ardından, istemci aldığı JWT erişim belirtecini, daha sonraki API çağrılarında kullanmak üzere güvenli bir şekilde saklamalıdır. İstemci tarafında JWT'yi bir bellekte saklamak yerine, güvenli bir çerez (httpOnly, Secure, SameSite) içinde saklamak XSS saldırılarına karşı daha iyi koruma sağlar, ancak CSRF koruması da bu durumda mutlaka uygulanmalıdır.

Servisler arası (service-to-service) iletişimde ise farklı bir yaklaşım gerekebilir. Bir mikroservisin diğerine yaptığı çağrılarda, istemci kimlik bilgileri akışı (client credentials grant) kullanılabilir. Bu akışta, her servis kendi kimliği ile (client ID ve secret) yetkilendirme sunucusundan, yalnızca kendisi için geçerli olan bir JWT erişim belirteci alır. Bu belirteç, servisler arası API çağrılarında kullanılır. Bu model, makineler arası güvenilir iletişimi sağlar ve insan kullanıcı bağlamı gerektirmez. Tüm bu entegrasyon modelleri, uygulama mimarisinin güvenli, sürdürülebilir ve gevşek bağlı olmasını destekler.

Performans ve Ölçeklenebilirlik

OAuth ve JWT tabanlı sistemlerin performansı, büyük ölçüde seçilen mimari desenlere ve uygulama ayrıntılarına bağlıdır. JWT'nin en büyük avantajı, durumsuz (stateless) olmasından kaynaklanan ölçeklenebilirliktir. Kaynak sunucusu (API), bir JWT'yi doğrulamak için sadece kriptografik imzayı kontrol eder; belirtecin geçerliliğini sorgulamak için yetkilendirme sunucusuna veya paylaşılan bir veritabanına başvurması gerekmez. Bu, her API isteğinin bağımsız olarak işlenebileceği anlamına gelir ve sunucu tarafında oturum durumu saklama ihtiyacını ortadan kaldırarak yatay ölçeklenmeyi son derece basitleştirir.

Ancak, bu performans kazancı bazı dengeler (trade-offs) gerektirir. JWT'ler, özellikle çok sayıda talep (claim) içerdiklerinde, geleneksel oturum tanımlayıcılarına (session ID) kıyasla daha büyük boyutlara ulaşabilir. Her HTTP isteğinin Authorization başlığında taşınan bu belirteçler, ağ üzerinde ek yük oluşturabilir. Bu yükü azaltmak için, kritik olmayan taleplerin JWT'den çıkarılması ve bunun yerine gerektiğinde bir kullanıcı servisinden alınması düşünülebilir. Ayrıca, JWT'nin payload kısmı şifrelenmediği sürce (JWE kullanılmadığı sürece) hassas bilgileri içermemelidir, çünkü bu bilgiler base64 decode edilerek okunabilir.

Ölçeklenebilirliği etkileyen bir diğer faktör, yenileme belirteçlerinin (refresh tokens) yönetimidir. Erişim belirteçlerinin aksine, yenileme belirteçleri genellikle iptal edilebilir olmaları için bir veritabanında saklanır. Bu, durumsuz olma avantajını kısmen zayıflatır. Bu sorunu hafifletmek için, yenileme belirteçlerinin ömrü dikkatlice yönetilmeli ve dağıtık bir önbellekleme sistemi (örneğin Redis kümesi) kullanılarak performans etkisi minimize edilmelidir. Dağıtık önbellek sistemleri, belirteç iptali ve karalama listesi kontrolü için merkezi ve hızlı bir nokta sağlar. Ayrıca, yetkilendirme sunucusunun kendisi de yüksek kullanılabilirlik (high availability) ve yatay ölçeklenme (horizontal scaling) için tasarlanmalıdır.

Sonuç olarak, performansı optimize etmek için belirteç boyutu ve ömrü dengesi gözetilmelidir. Çok kısa ömürlü erişim belirteçleri, yenileme işlemlerinin sıklığını artırarak yetkilendirme sunucusuna yük bindirebilir. Çok uzun ömürlü belirteçler ise güvenlik riski oluşturur. İyi bir strateji, tipik bir kullanıcı oturumu süresine göre kısa (dakikalar/saatler) erişim belirteci ve daha uzun (günler/haftalar) ama iyi korunan yenileme belirteci kullanmaktır. Bu yaklaşım, hem güvenliği hem de sistem yükünü ve kullanıcı deneyimini dengeler.