Blog'a Dön

Buğra Şıkel

Opaque Token mı Yoksa Stateless JWT mi? Anında Yetki İptali Odaklı Karar Matrisi

Opaque Token mı Yoksa Stateless JWT mi? Anında Yetki İptali Odaklı Karar Matrisi

Giriş

Dağıtık sistem mimarilerinde kimlik doğrulama (authentication) ve yetkilendirme (authorization) süreçleri tasarlanırken karşılaşılan en temel mimari kararlardan biri, oturum durumunun (state) nerede ve nasıl tutulacağıdır. İstemci ile sunucu arasındaki güven ilişkisi kurulduktan sonra, bu ilişkinin her istekte yeniden doğrulanması gerekir. Bu noktada mühendislik ekipleri iki ana akım yaklaşımla karşı karşıya kalır: Durumlu (stateful) yapısıyla bilinen Opaque Token ve durumsuz (stateless) doğasıyla öne çıkan JSON Web Token (JWT).

Teorik düzlemde durumsuz mimariler yatay ölçeklenebilirlik açısından avantajlı görünse de, işin içine “anında yetki iptali” (instant revocation) gereksinimi girdiğinde mimari sınırlar belirmeye başlar. Çalınan bir cihaz, şifre sıfırlama işlemi veya bir kullanıcının yetkilerinin sistem yöneticisi tarafından acil olarak düşürülmesi gibi senaryolar, sistemin bir oturumu saniyeler içinde geçersiz kılmasını zorunlu kılar. Durumsuz bir JWT’yi süresi dolmadan iptal etmeye çalışmak, tanımı gereği durumsuzluk ilkesiyle çelişir ve mimariyi karmaşıklaştırır.

Karar sürecinde, sistemin gecikme bütçesi (latency budget), veritabanı okuma kapasitesi ve güvenlik gereksinimleri arasında bir ödünleşim (trade-off) analizi yapılmalıdır. Hedeflenen mimarinin gereksinimleri, hangi token stratejisinin seçileceğini doğrudan belirler.

İçindekiler

  • Opaque Token ve JWT’nin Yapısal Anatomisi
  • Anında Yetki İptali (Instant Revocation) Paradoksu
  • Karar Matrisi: Kriterlere Göre Karşılaştırma
  • Durum Senaryoları: Eğer X ise -> Y Formatında Karar Ağacı
  • Hibrit Mimari Çözümü: Phantom Token Pattern
  • Referans Uygulama: Redis Destekli Token Doğrulama
  • Pratik Öneriler ve Production Notları
  • Sık Sorulan Sorular
  • Sonuç

Opaque Token ve JWT’nin Yapısal Anatomisi

Opaque Token (Durumlu / Stateful)

Opaque Token, kelime anlamı itibarıyla “saydam olmayan”, kendi içinde kullanıcıya veya yetkilerine dair okunabilir bir veri barındırmayan rastgele üretilmiş bir karakter dizisidir (genellikle UUIDv4 veya yüksek entropili kriptografik bir string). İstemci bu token’ı sunucuya gönderdiğinde, sunucunun bu dizgenin kime ait olduğunu ve geçerli olup olmadığını anlamak için bir veri deposuna (genellikle Redis veya Memcached gibi bellek içi bir veritabanı) başvurması gerekir.

Bu yapının temel özelliği, kontrolün tamamen sunucu tarafında olmasıdır. Veritabanındaki kayıt silindiği milisaniye itibarıyla token geçersiz hale gelir.

Stateless JWT (Durumsuz / Stateless)

JSON Web Token (JWT), RFC 7519 standardıyla tanımlanmış, Header, Payload ve Signature olmak üzere üç bölümden oluşan, Base64Url ile kodlanmış bir formattır. Payload kısmı kullanıcının kimliğini (sub), yetkilerini (roles) ve token’ın son kullanma tarihini (exp) açıkça barındırır. Sunucu, JWT’yi doğrularken veritabanına gitmek yerine sadece kriptografik imzayı (örneğin HMAC SHA-256 veya RSA) doğrular.

İmza geçerliyse ve exp (expiration) tarihi henüz geçmemişse, sunucu token içindeki bilgilere güvenir. Veritabanı sorgusu gerektirmemesi, mikroservis ağlarında ağ gecikmesini (network latency) ve merkezi veritabanı yükünü ortadan kaldırır.

Anında Yetki İptali (Instant Revocation) Paradoksu

Anında yetki iptali, bir sistemin dışarıdan gelen bir tetikleme ile mevcut bir oturumu derhal sonlandırabilme yeteneğidir. Dağıtık mimarilerde bu gereksinim, JWT’nin en zayıf noktasıdır.

Eğer bir JWT’nin süresi (TTL) 1 saat olarak belirlenmişse ve kullanıcı 5. dakikada şifresini değiştirirse, geriye kalan 55 dakika boyunca eski token teorik olarak geçerliliğini korur. Sunucu token’ı doğrularken veritabanına bakmadığı için şifre değişikliğinden haberdar olamaz. Bu problemi çözmek için başvurulan yöntemler şunlardır:

  • Deny List (Kara Liste): İptal edilen JWT’lerin benzersiz ID’lerinin (jti) süresi dolana kadar bir önbellekte (Redis) tutulması. Her istekte bu listeye bakılması gerekir.
  • Allow List (Beyaz Liste): Sadece aktif oturumların listesinin tutulması.

JWT doğrulaması için her istekte Redis üzerindeki bir Deny List’e veya Allow List’e bakıyorsanız, mimariniz artık durumsuz (stateless) değildir. JWT’nin getirdiği CPU bazlı imza doğrulama maliyetine ek olarak, Opaque token’ın getirdiği ağ tabanlı veritabanı erişim maliyetini de üstlenmiş olursunuz.

Karar Matrisi: Kriterlere Göre Karşılaştırma

Aşağıdaki matris, iki farklı token tipinin belirli sistem gereksinimleri altındaki karakteristiklerini karşılaştırmaktadır.

Değerlendirme Kriteri Opaque Token Stateless JWT
Yetki İptal Hızı Anında (Veritabanından silindiğinde biter) Gecikmeli (Süresi dolana kadar geçerli)
Sunucu Yükü Modeli Yüksek I/O (Her istekte DB/Cache okuması) Yüksek CPU (Her istekte kriptografik doğrulama)
Ağ Bant Genişliği (Bandwidth) Düşük (Kısa bir string, örn: 32-64 byte) Yüksek (Header+Payload+Sign, örn: 500-1500 byte)
Yatay Ölçeklenebilirlik Merkezi Cache kapasitesiyle sınırlı Bağımsız, sınırsız yatay genişleme
İstemci Tarafı Bilgi Çıkarımı Yok (Sadece sunucu anlamlandırabilir) Var (Payload decode edilerek veri okunabilir)

Durum Senaryoları: Eğer X ise -> Y Formatında Karar Ağacı

Kullanım senaryolarının sınırlarını belirlemek, doğru tercihi yapmanın temelidir. Çoğu durumda karar, güvenlik riskleri ile altyapı maliyetleri arasındaki dengeye bağlıdır.

  • EĞER uygulamanız yüksek güvenlik gerektiren bir finans, sağlık veya ödeme sistemi ise ve oturumun çalınması durumunda saniyeler içinde iptal edilmesi yasal veya iş gereksinimi ise -> OPAQUE TOKEN KULLANIN. Merkezi bir Session DB üzerinden mutlak kontrol sağlayın.
  • EĞER mimariniz, saniyede on binlerce istek (RPS) alan, çok sayıda bağımsız mikroservis içeren ve iç ağdaki (internal network) yetki kontrollerinin veritabanına gidilmeden çözülmesi gereken bir yapıdaysa -> STATELESS JWT KULLANIN.
  • EĞER anında yetki iptaline ihtiyacınız var ancak JWT’nin durumsuz yapısından vazgeçmek istemiyorsanız -> KISA ÖMÜRLÜ JWT (Short-Lived JWT) + OPAQUE REFRESH TOKEN KULLANIN. JWT süresini 5 dakika gibi kısa bir süreye ayarlayın. İptal durumunda maksimum 5 dakikalık bir güvenlik riski kabul edilir.
  • EĞER API’nizi dışarıya (3rd party) açıyorsanız ve token içeriğinin veya yetki sınırlarının istemci tarafından görülmesini istemiyorsanız -> OPAQUE TOKEN KULLANIN. JWT, Base64 formatında olduğu için hassas iş kurallarını açığa çıkarabilir.

Hibrit Mimari Çözümü: Phantom Token Pattern

Dağıtık sistemlerde hem güvenlik (anında iptal) hem de iç ağ performansı istendiğinde, en yaygın kullanılan mimari desen Phantom Token Pattern‘dir.

Bu yapıda, istemciye sadece bir Opaque Token verilir. İstemci internet üzerinden API Gateway’e bu Opaque Token ile gelir. API Gateway, arka plandaki Redis veya Session veritabanına giderek Opaque Token’ı doğrular ve kullanıcının yetki setini çeker. Ardından Gateway, bu verileri kullanarak kendi içinde bir JWT oluşturur ve iç ağdaki mikroservislere bu JWT’yi iletir.

Bu senaryonun kazanımları şunlardır:

  1. Dış Ağ (External Network): İstemci Opaque Token tuttuğu için yetki iptali anında yapılabilir.
  2. İç Ağ (Internal Network): Mikroservisler kendi aralarında iletişim kurarken Redis’e veya merkezi bir veritabanına bağımlı kalmaz, sadece Gateway’in imzaladığı JWT’yi CPU bazlı doğrular.
  3. Gizlilik: İstemci, JWT içeriğini (roller, tenant ID’ler) göremez.

Referans Uygulama: Redis Destekli Token Doğrulama

Aşağıdaki Go dili ile yazılmış temsilî kod bloğu, Opaque Token veya Deny List kontrolü için Redis tabanlı bir doğrulama mekanizmasının nasıl kurgulanabileceğini göstermektedir. Bu kod, mikroservis veya Gateway seviyesinde çalıştırılabilecek bir katmanı ifade eder.

package auth

import (
	"context"
	"encoding/json"
	"errors"
	"time"

	"github.com/go-redis/redis/v8"
)

type UserSession struct {
	UserID string   `json:"user_id"`
	Role   string   `json:"role"`
	Status string   `json:"status"`
}

// ValidateOpaqueToken, istemciden gelen token'ı Redis üzerinden doğrular
// Gecikme bütçesine (latency budget) dikkat edilmesi kritik bir noktadır.
func ValidateOpaqueToken(ctx context.Context, rdb *redis.Client, token string) (*UserSession, error) {
	// Token doğrulama işlemi için maksimum 50ms'lik bir timeout belirliyoruz.
	// Dağıtık sistemlerde bloklanmaları önlemek için timeout hayati önem taşır.
	ctxTimeout, cancel := context.WithTimeout(ctx, 50*time.Millisecond)
	defer cancel()

	// Redis üzerinden token state'ini çek (Time Complexity: O(1))
	val, err := rdb.Get(ctxTimeout, "session:"+token).Result()
	if err == redis.Nil {
		// Token Redis'te yoksa ya hiç var olmamıştır ya da iptal edilmiştir (Revoked).
		return nil, errors.New("unauthorized: token invalid or revoked")
	} else if err != nil {
		// Redis erişim hatası (Fail-closed veya Fail-open karar noktası)
		return nil, err
	}

	var session UserSession
	if err := json.Unmarshal([]byte(val), &session); err != nil {
		return nil, errors.New("internal: session data corrupted")
	}

	if session.Status != "active" {
		return nil, errors.New("unauthorized: account suspended")
	}

	return &session, nil
}

Pratik Öneriler ve Production Notları

Token mimarisini canlı ortama (production) alırken sistemin ayakta kalmasını sağlayacak operasyonel kararlar alınmalıdır:

  • Gecikme (Latency) İzleme: Opaque token kullanıyorsanız, token validasyonu için yapılan her Cache/DB isteğinin gecikme süresi (P95 ve P99 metrikleri) izlenmelidir. Ağ darboğazları ilk olarak burada kendini gösterir.
  • Fail-Open vs Fail-Closed Stratejisi: Cache sunucusu (örneğin Redis) çöktüğünde sistemin nasıl davranacağına karar verilmelidir. Fail-closed yaklaşımında, Cache’e ulaşılamıyorsa tüm istekler reddedilir (güvenlik yüksek, erişilebilirlik düşük). Fail-open yaklaşımında ise Cache çökse bile (eğer JWT blocklist kontrolü yapılıyorsa) JWT’nin kendi süresine güvenilerek isteğe izin verilir.
  • Bloom Filters (Bellek Optimizasyonu): JWT için bir Deny List (Kara liste) kullanıyorsanız ve sistemde milyonlarca iptal edilmiş token varsa, Redis üzerinde bellek tüketimini azaltmak için Bloom Filter veri yapısını kullanmayı değerlendirin. Bloom Filter, bir token’ın kara listede olup olmadığını çok düşük bellek ayak izi ile istatistiksel olarak doğrulayabilir.
  • Saat Kayması (Clock Skew) Toleransı: JWT kullanırken mikroservislerin sunucu saatleri arasında milisaniyelik veya saniyelik farklar olabilir. JWT kütüphanelerinde doğrulama yaparken her zaman 5-10 saniyelik bir Clock Skew toleransı tanımlayın.

Sık Sorulan Sorular

JWT’nin süresini (TTL) çok kısa tutarsam, iptal sorununu çözmüş olur muyum?

Evet, JWT’nin geçerlilik süresini (örneğin 3 dakika) kısa tutmak, anında iptal ihtiyacını 3 dakikalık bir güvenlik riskine indirger. İptal anından itibaren en geç 3 dakika içinde token doğal olarak geçersiz kalır. Bu süre zarfında kullanıcı, daha uzun ömürlü ve sunucu tarafında doğrulanabilen (Opaque) bir Refresh Token ile arka planda yeni bir JWT alır.

JWT Deny List veritabanını ne zaman temizlemeliyim?

Deny List’e eklenen bir JWT’nin ID’sini (jti), sonsuza kadar veritabanında tutmanıza gerek yoktur. İlgili JWT’nin orijinal son kullanma tarihi (exp) geçtiğinde, o token zaten kriptografik olarak doğrulanamayacağı için Deny List’ten güvenle silinebilir. Redis üzerinde kayıt oluştururken, anahtarın TTL değerini JWT’nin kalan süresi kadar ayarlamak bu işlemi otomatikleştirir.

Phantom Token mimarisinde API Gateway tek nokta hatası (SPOF) yaratmaz mı?

Eğer Gateway yeterince ölçeklendirilmemişse yaratabilir. Ancak günümüz altyapılarında (Envoy, Kong, Nginx gibi), Gateway katmanı genellikle CPU ve bellek açısından yatay olarak (horizontal scaling) yüksek kapasitelere çıkabilecek şekilde yapılandırılır. Asıl darboğaz, Gateway’in doğrulama için gittiği Session veritabanında (Redis cluster vb.) oluşma eğilimindedir.

Opaque Token’lar kriptografik olarak imzalanmalı mıdır?

Gerekli değildir. Opaque Token’ın güvenliği, içeriğindeki veriden değil, yüksek entropisinden (tahmin edilemezliğinden) ve HTTPS üzerinden şifreli iletilmesinden gelir. Ancak yetkisiz bir sistemin sahte token’larla veri tabanınızı meşgul etmesini engellemek için, Opaque token’ın sonuna basit bir HMAC imzası eklemek, DB sorgusu yapmadan önce formasyonun size ait olup olmadığını anlamanızı sağlayabilir.

Sonuç

Opaque Token ve Stateless JWT arasında yapılacak seçim, birinin diğerinden mutlak üstünlüğüne değil, projenin mevcut sistem altyapısına ve güvenlik kültürüne dayanır. İç ağ iletişiminde CPU kaynaklarını öne çıkaran yatay ölçeklenebilirlik aranıyorsa JWT; her an kontrol altında tutulması gereken dışa açık oturum yönetimleri için ise Opaque Token tercih edilmelidir.

Eğer sisteminizi sıfırdan tasarlıyorsanız, dış dünyada Opaque Token, mikroservisler arası iletişimde ise Gateway üzerinden dönüştürülmüş kısa ömürlü JWT kullanan Phantom Token desenini uygulamak üzere mimarinizi yapılandırmaya başlayın. Bu yapı, hem anında yetki iptalini sağlar hem de iç ağdaki bağımlılıkları minimize eder.

Bunları da beğenebilirsiniz

Yüksek Hacimli Sensör Verileri İçin AI Destekli Asenkron Kuyruk Yönetimi Stratejileri: Performans ve Verimlilik Optimizasyonu

Bu blog yazısı, IoT ve endüstriyel otomasyon gibi alanlarda yüksek hacimli sensör verilerini işlemek için yapay zeka destekli asenkron kuyruk yönetimi stratejilerini inceliyor. Gecikmeyi azaltma, ölçeklenebilirliği artırma ve kaynak kullanımını optimize etme yöntemlerini keşfedin.

Devamını Oku

PHP ile İletişim Formlarındaki Spam Mesajları Engelleme

Merhabalar, bu içeriğimizde sayfalarımızda oldukça sık kullandığımız iletişim formlarına botlar tarafından bırakılan spam mesajları engellemenin bir kaç yönteminden bahsedeceğim. Bahsettiğim yöntemler %100 garantili olmamakla birlikte…

Devamını Oku

PHP ile TC Kimlik Numarası Doğrulama Fonksiyonu

Türkiye Cumhuriyeti Kimlik Numarası (TC Kimlik No), ülkemizde bireylerin kimliğini doğrulamak için kullanılan 11 haneli benzersiz bir sayısal koddur. Web uygulamaları geliştirenler için, bu numaranın…

Devamını Oku