JSON Web Token'lar popülerdir, çünkü bir API onları kimseyi çağırmadan kontrol edebilir: imzayı doğrula, claim'leri oku, bitti. Bu özellik aynı zamanda JWT sorunlarının çoğunun kaynağıdır. Sorgulayamadığınız bir token geri çağıramadığınız bir token'dır ve ekipler bunu bir dizüstü bilgisayar çalındığında ya da bir çalışan ayrıldığında ilk kez fark eder.
Bu yazı erişim token'ları, yenileme token'ları ve bir sekans diyagramıyla eksiksiz bir JWT kimlik doğrulama akışını adım adım anlatıyor; ardından her API'nin ihtiyaç duyduğu doğrulama kontrollerini, token'ların tarayıcıda nerede tutulacağını, yenileme token'ı döndürmeyi, anahtar yenilemeyi ve iptal için gerçekçi seçenekleri ele alıyor.
JWT nedir, ne değildir
Bir JWT (RFC 7519), noktalarla ayrılmış üç base64url parçasından oluşan, kompakt ve URL için güvenli bir dizedir: bir başlık, claim'lerden oluşan bir payload ve bir imza. Çözüldüğünde bir erişim token'ı şöyle görünür:
{ "alg": "RS256", "kid": "2026-10", "typ": "at+jwt" }
{
"iss": "https://auth.example.com",
"sub": "user_8412",
"aud": "orders-api",
"scope": "orders:read orders:write",
"iat": 1793606400,
"exp": 1793607300,
"jti": "a3f1c9e2"
}
Yanlış anlamaların çoğuna üç nokta yol açar:
- İmzalı bir JWT şifreli değildir. Token'ı elinde tutan herkes payload'u okuyabilir. Sahibinin görmemesi gereken sırları ya da kişisel verileri içine koymayın.
- JWT bir protokol değil, bir biçimdir. Bir istemcinin token'ı nasıl edindiği başka bir yerde, genellikle OAuth 2.0 ve OpenID Connect ile tanımlanır. OAuth 2.0 akış diyagramı o kısmı ele alıyor.
- Bir akıştaki her token JWT değildir. Erişim token'ları çoğu zaman JWT'dir; yenileme token'ları ise çoğu zaman yalnızca yetkilendirme sunucusunun sorgulayabildiği opak rastgele dizelerdir.
Her token'da karşılaşacağınız kayıtlı claim'ler:
| Claim | Anlamı | Kim kontrol eder |
|---|---|---|
iss |
Issuer, token'ı imzalayan yetkilendirme sunucusu | API |
sub |
Subject, genellikle kullanıcı ID'si | API, yetkilendirme için |
aud |
Audience, token'ın hedeflendiği API | API |
exp, nbf, iat |
Epoch'tan bu yana saniye cinsinden bitiş, başlangıç ve veriliş zamanı | API |
jti |
Benzersiz token ID'si, engelleme listeleri için kullanışlı | API ya da ağ geçidi |
Adım adım akış
- Giriş. Kullanıcı, genellikle PKCE'li OAuth yetkilendirme kodu akışıyla yetkilendirme sunucusunda kimliğini doğrular.
- Token yanıtı. Yetkilendirme sunucusu kısa ömürlü bir erişim token'ı (bir JWT, örneğin 15 dakikalık) ve uzun ömürlü bir yenileme token'ı döndürür.
- API çağrısı. Uygulama her istekle birlikte
Authorization: Bearer <access token>gönderir. - Yerel doğrulama. API imzayı, JWKS uç noktasından bir kez alıp önbelleğe koyduğu yetkilendirme sunucusunun açık anahtarıyla doğrular, ardından claim'leri kontrol eder. İstek başına yetkilendirme sunucusuna çağrı yapılmaz.
- Süre dolumu. 15 dakika sonra API
401 Unauthorizeddöndürür. - Yenileme. Uygulama yenileme token'ını yetkilendirme sunucusunun token uç noktasına gönderir ve yeni bir erişim token'ı ile, döndürme kullanılıyorsa, yeni bir yenileme token'ı alır.
- Tekrar deneme. Uygulama başarısız isteği yeni erişim token'ıyla tekrarlar.
Ekiplerin JWT'yi seçme nedeni 3. ve 4. adımlardır: binlerce API isteği ve paylaşılan bir oturum deposu yok. 5. ve 6. adımlar bunun bedelidir ve güvenlik çalışmasının çoğu oradadır.
Bir token'ı doğrulamak: kontrol listesi
JWT kabul eden her API aynı kontrolleri bu sırayla çalıştırmalıdır:
- Yalnızca beklediğiniz algoritmalara izin verin.
algbaşlığını asla göründüğü gibi kabul etmeyin. RFC 8725 iki klasik saldırıyı anlatır:algdeğerininnoneyapılması ve bir RS256 token'ının HS256 olarak yeniden yazılması; böylece saf bir kütüphane onu açık anahtarı HMAC sırrı gibi kullanarak doğrular. - Anahtarı önbellekteki JWKS'ten
kidile seçin ve bilinmeyen birkidgördüğünüzde seti yeniden çekin; bunu kısa bir aralıkta en fazla bir kez yapın. - İmzayı doğrulayın.
issveauddeğerlerini kontrol edin. Başka bir API için verilmiş bir token burada başarısız olmalıdır.expvenbfdeğerlerini 60 saniye gibi küçük bir saat toleransıyla kontrol edin.- Token türünü kontrol edin. RFC 9068 erişim token'ları
typ: at+jwttaşır; bu, bir ID token'ının erişim token'ı gibi tekrar oynatılmasını engeller. - Ardından yetkilendirin: scope'lar, roller ve kaynağın sahipliği.
Node.js'te jose kütüphanesiyle listenin çoğu tek bir çağrıdır:
import { createRemoteJWKSet, jwtVerify } from 'jose'
const JWKS = createRemoteJWKSet(new URL('https://auth.example.com/.well-known/jwks.json'))
export async function verifyAccessToken(token: string) {
const { payload } = await jwtVerify(token, JWKS, {
issuer: 'https://auth.example.com',
audience: 'orders-api',
algorithms: ['RS256'],
typ: 'at+jwt',
clockTolerance: 60,
})
return payload // scopes and sub are checked by the caller
}
Bir erişim token'ı ne kadar yaşamalı?
Ömür, çalınmış bir token'ın çalıştığı ve geri çağrılamadığı penceredir. Daha kısa, daha güvenli ve daha fazla yenileme trafiği demektir. Sekiz saatlik bir iş günü boyunca etkin olan bir kullanıcı için:
| Erişim token'ı ömrü | Çalınırsa açık kalma süresi | Kullanıcı başına günlük yenileme |
|---|---|---|
| 5 dakika | 5 dakika | 96 |
| 15 dakika | 15 dakika | 32 |
| 1 saat | 1 saat | 8 |
| 24 saat | 24 saat | 1 |
Çoğu ekip erişim token'ları için 5 ile 15 dakika arasında karar kılar. Bir günlük erişim token'ı, iptal edemediğiniz bir oturum çerezidir.
Yenileme token'ı döndürme
Bir yenileme token'ı günlerce ya da haftalarca yaşar; bu yüzden birinin sızması bir erişim token'ının sızmasından daha kötüdür. OAuth güvenliği için güncel en iyi uygulama olan RFC 9700, tarayıcı ve mobil uygulamalar gibi açık istemcilerin tuttuğu yenileme token'ları için iki korumadan birini zorunlu tutar:
- Göndericiye bağlı yenileme token'ları: Karşılıklı TLS ya da DPoP ile istemcinin tuttuğu bir anahtara bağlanır.
- Döndürme: Her yenileme yeni bir yenileme token'ı döndürür ve eskisini geçersiz kılar; yetkilendirme sunucusu da zinciri hatırlar. Bir saldırgan ve gerçek istemci aynı token'ı kullanırsa, biri geçersiz kılınmış bir token sunar ve sunucu etkin yenileme token'ını iptal eder; bu da zinciri ikisi için de sonlandırır.
Döndürme, çalınmış bir yenileme token'ını haftalarca süren bir sorundan, meşru istemcinin bir sonraki yenilemesinde biten bir soruna dönüştürür. Bedeli: Kullanıcının yeniden giriş yapması gerekir ve token uç noktanızın, aynı anda yenileme yapan iki sekmeyi yeniden kullanım tespitini tetiklemeden idare etmesi gerekir; bu genellikle kısa bir tolerans süresiyle yapılır.
Token'lar tarayıcıda nerede tutulmalı
| Depolama | JavaScript okuyabilir mi | Asıl risk | Notlar |
|---|---|---|---|
localStorage |
Evet | Herhangi bir XSS token'ları çalabilir | Yeniden yüklemelerde kalır; yenileme token'ları için kaçının |
| Yalnızca bellek | Evet, sayfa yaşadığı sürece | Oturum sırasında XSS | Yeniden yüklemede kaybolur; açılışta yenileyin |
HttpOnly çerez |
Hayır | CSRF | Secure, SameSite ve durum değiştiren istekler için CSRF token'ları kullanın |
| Backend for frontend | Hayır; token'lar sunucuda kalır | Sunucu tarafında oturum yönetimi | Tarayıcı yalnızca bir oturum çerezi tutar |
IETF'in tarayıcı tabanlı uygulamalarda OAuth üzerine taslak rehberi, backend for frontend desenini token'ları JavaScript'ten tamamen uzak tutan seçenek olarak tanımlar. Token'ları tarayıcıda tutuyorsanız erişim token'ını bellekte, yenileme token'ını da token uç noktasıyla sınırlandırılmış bir HttpOnly çerezde tutun.
İptal: gerçekte ne işe yarar
Bir JWT'nin imzasını geri alamazsınız. Yalnızca API'nin onu kabul etmeyi bırakmasını sağlayabilirsiniz ve her seçenek durumsuzluğun bir kısmını geri verir:
| Strateji | Nasıl çalışır | Maliyet |
|---|---|---|
| Kısa süre | Token'lar dakikalar içinde kendiliğinden ölür | Yok; açık kalma penceresi sürer |
| Yenileme token'ını iptal etmek | Sonraki yenileme başarısız olur, erişim bir sonraki süre dolumunda biter | Zaten durumu olan token uç noktasında tek bir sorgu |
jti ile engelleme listesi |
Ağ geçitleri listedeki ID'leri exp değerlerine kadar reddeder |
Her istekte kontrol edilen paylaşılan bir önbellek |
| Kullanıcı bazında kesim | O kullanıcı için saklanan bir zaman damgasından önce verilen token'ları reddet | Kullanıcı başına bir sorgu, önbelleğe alınabilir |
| Introspection | API her token'ı yetkilendirme sunucusuna sorar (RFC 7662) | Bir ağ çağrısı; yalnızca yüksek riskli uç noktalar için kullanın |
Pratik bir kombinasyon: 15 dakika ya da daha kısa erişim token'ları, çıkışta ve parola değişikliğinde iptal edilen döndürülen yenileme token'ları ve nadir görülen “her yerden hemen çıkış yap” durumu için kullanıcı bazında bir kesim.
İmzalama anahtarlarını yenilemek
Anahtarlar sızar ve algoritmalar eskir; bu yüzden yenilemeyi ilk günden planlayın. Yeni açık anahtarı, onunla imzalamaya başlamadan bir gün kadar önce JWKS'te yayımlayın ki her API önbelleğinde bulunsun. İmzalamayı yeni kid değerine geçirin. Eski anahtarı, onunla imzalanmış son token'ın süresi dolana kadar JWKS'te tutun, sonra kaldırın. Bilinmeyen bir kid gördüğünde yeniden çeken bir API, acil bir anahtar yenilemesini yeniden başlatma olmadan atlatır.
JWT akış diyagramı
Diyagram içeriği
- Browser app
- Auth server
- Orders API
- access token expired
- 1. Sign in (OAuth code flow + PKCE)
- 2. Access token (JWT, 15 min) + refresh token
- 3. GET /orders, Authorization: Bearer JWT
- GET /.well-known/jwks.json (once, then cached)
- public keys
- 4. 200 OK
- 5. GET /orders (expired JWT)
- 6. 401 Unauthorized
- 7. POST /token (refresh token)
- 8. New token pair, old refresh token invalidated
- 9. Retry GET /orders with new JWT
- 10. 200 OK
Nasıl okunur:
- Üç yaşam çizgisi. Solda tarayıcı uygulaması, ortada yetkilendirme sunucusu, sağda sipariş API'si. Zaman aşağı doğru akar.
- Giriş ve token yanıtı en üsttedir: Uygulama bir erişim token'ı ve bir yenileme token'ı alır.
- Mutlu yol: API'ye bearer isteği ve yanıtı. API token'ı önbellekteki JWKS anahtarlarıyla doğrular ve yetkilendirme sunucusunu asla çağırmaz.
- Opt parçası süre dolumunu kapsar:
401, yenileme, eski yenileme token'ı geçersiz kılınmış yeni bir token çifti ve tekrarlanan istek. - Markdown bloğu çözülmüş token'ı ve doğrulama kontrollerini gösterir.
İnceleyenlerin kontrol edebileceği kimlik doğrulama akışları çizmek
- Her oktaki her token'ı adlandırın, türü ve ömrüyle: “erişim token'ı (JWT, 15 dk)”. Hangi token'ın nereye gittiğine dair belirsizlik gerçek hataları gizler.
- Doğrulamanın nerede yapıldığını gösterin. İmzayı doğrulayan yaşam çizgisine bir not koyun ve anahtarlarının nereden geldiğini yazın.
- Hata yollarını çizin. Süre dolumu, yenileme token'ının yeniden kullanımı ve çıkış parçalara aittir; olayların çoğu orada başlar.
- Sırları resmin dışında tutun. Yer tutucu değerler kullanın; diyagramlar beklediğinizden daha geniş bir çevreyle paylaşılır.
Sekans diyagramı örneği yaşam çizgilerini ve parçaları ayrıntılı ele alıyor; sıfır güven mimari diyagramı ise token kontrollerinin daha geniş bir erişim modelinde nerede durduğunu gösteriyor.
Archboard'da oluşturun
- Google ya da GitHub ile giriş yapın ve bir diyagram oluşturun.
- Sekans paketinden üç Yaşam çizgisi düğümü ekleyin: Browser app, Auth server ve Orders API.
- Mesajları yukarıdan aşağıya yaşam çizgileri arasındaki kenarlar olarak çizin: giriş, token yanıtı, bearer isteği ve yanıtı. Her birini taşıdığı token'la etiketleyin.
- Süre dolumu yolunun etrafına, işleci
optolan bir Sekans paketi Parça düğümü ekleyin:401, yenileme isteği, yeni token çifti, tekrar deneme. - Çözülmüş token ve doğrulama kontrol listesiyle Temel paketinden bir Markdown bloğu ekleyin.
Örnek 5 diyagram düğümü kullanıyor ve Free planın sınırları içinde kalıyor.
SSS
JWT'ler şifreli midir? İmzalı JWT'ler değildir. Payload base64url ile kodlanmıştır ve token'a sahip herkes tarafından okunabilir. Şifreli token'lar için JSON Web Encryption vardır, ancak erişim token'larının çoğu yalnızca imzalıdır.
Bir JWT'yi localStorage'da saklamalı mıyım? Uzun ömürlü hiçbir şey için saklamayın. Herhangi bir siteler arası betik çalıştırma (XSS) hatası localStorage'ı okuyabilir. Erişim token'larını bellekte, yenileme token'larını bir HttpOnly çerezde tutun ya da token'ları bir backend for frontend'de saklayın.
JWT'ler durumsuzken bir kullanıcının oturumunu nasıl kapatırım? Yeni erişim token'ı verilmesin diye yenileme token'ını iptal edin ve erişim token'larını kısa tutun. Anında etki için API'nizin kontrol ettiği kullanıcı bazında bir kesim zaman damgası ya da bir jti engelleme listesi ekleyin.
ID token ile erişim token'ı arasındaki fark nedir? ID token istemciye kimin giriş yaptığını söyler ve istemci içindir. Erişim token'ı ise bir API içindir. API'ler ID token'larını reddetmelidir; typ ve aud kontrolleri bunu açık hâle getirir.
HS256 mı kullanmalıyım, RS256 mı? HS256 tek bir paylaşılan sır kullanır; bu yüzden token doğrulayan her servis token da üretebilir. RS256 ya da ES256, API'lerin açık anahtarla doğrulamasına izin verirken özel anahtarı yalnızca yetkilendirme sunucusunda tutar; birden fazla servis için daha güvenli varsayılan budur.