JWT (JSON Web Token), modern web uygulamalarında kullanıcı kimlik doğrulamasını ve bilgilerin güvenli bir şekilde paylaşımını sağlamak için kullanılan hafif bir mekanizmadır. Özellikle stateless (durumsuz) mimarideki uygulamalar için ideal bir çözümdür.
JWT Nedir?
JSON Web Token (JWT), iki taraf arasında güvenli bir şekilde bilgi aktarımı için kullanılan açık standart (RFC 7519) bir formattır. JSON formatında olan bu token, üç parçadan oluşur: Header (başlık), Payload (yük) ve Signature (imza).
JWT Parçaları
-
Header: JWT’nin algoritmasını ve türünü belirtir. Genellikle
algvetypalanlarını içerir. Örnek:{ "alg": "HS256", "typ": "JWT" } -
Payload: Token içerisinde taşınan aslî veridir. Kullanıcı bilgileri, roller, izinler veya başka özel veriler bu bölümde yer alır. Doğruluk kontrolü yapılmadığı sürece bu veri herkes tarafından okunabilir.
-
Signature: Token’ın bütünlüğünü korumak amacıyla oluşturulan imzadır. Header ve Payload HMACSHA256 gibi bir algoritma ile imzalanır.
JWT ile Kimlik Doğrulama Akışı
JWT ile kimlik doğrulama işlemi temelde şu şekilde çalışır:
- Kullanıcı, kullanıcı adı ve şifre ile giriş isteği gönderir.
- Sunucu, kullanıcı bilgilerini doğrularsa, bir JWT üretir ve istemciye gönderir.
- İstemci, bu token'ı sonraki tüm isteklerin Authorization başlığına
Bearer {token}biçiminde ekler. - Sunucu, gelen token'ı doğrular ve geçerliyse isteği işler.
Örnek JWT Üretimi (Node.js)
const jwt = require('jsonwebtoken'); const user = { id: 1, username: 'user1', role: 'admin' }; const secretKey = 'mysecret'; const token = jwt.sign(user, secretKey, { expiresIn: '1h' }); console.log(token);
Token Doğrulama
Token doğrulanırken hem imzanın hem de sürenin kontrolü yapılmalıdır. Örnek:
jwt.verify(token, secretKey, (err, decoded) => { if (err) { return res.status(401).send('Yetkisiz erişim!'); } req.user = decoded; // Token’dan gelen veriler kullanıcı nesnesi olarak atanır next(); });
Güvenlik Önlemleri
JWT kullanımı sırasında uyulması gereken bazı önemli güvenlik önlemleri vardır:
-
Kısa süreli token kullanımı: Token’ın ömrü kısa olmalıdır. Eğer token çalınırsa daha az zarar verir.
-
HTTPS kullanımı: Token'lar açık bir şekilde taşındığı için, TLS olmadan iletildiğinde ortadaki adam saldırılarına (MiTM) açık hale gelir.
-
Token yenileme mekanizması (Refresh Token): Erişim token’larının süresinin kisa olması nedeniyle kullanıcı çıkış yapmadan yeni token alabilmeli. Bu, refresh token yapısıyla sağlanır.
Access Token ve Refresh Token Kullanımı
JWT, hem Access Token hem de Refresh Token olarak rol alabilir:
- Access Token: Kısa ömürlüdür ve API erişimlerinde kullanılır.
- Refresh Token: Daha uzun ömürlüdür ve yalnızca yeni access token üretmek için kullanılır.
Token yenileme için tipik senaryo:
- Kullanıcı başarıyla giriş yaptığında, hem access hem de refresh token sunucu tarafından üretilir.
- Access token süresi sona erdiğinde istemci, refresh token ile bir endpoint'e başvurarak yeni access token alır.
- Refresh token da süresini doldurduysa veya iptal edildiyse, kullanıcı tekrar giriş yapmak zorundadır.
Blacklist ve Token İptali
JWT'lerin stateless yapısı, genellikle sunucuda oturum tutmayı gereksiz hale getirir. Ancak bu, token’ın geçerliliğini iptal etmeyi zorlaştırır. Bir kullanıcı sistemden çıkış yaptığında veya token çalındığında, bu token’ı nasıl iptal edeceğimizi hesaplamalıyız. Bu hedefle kara liste (blacklist) yapısı kullanılabilir.
- Redis gibi bellek tabanlı veritabanında iptal edilen token değerleri saklanabilir.
- Her API isteğinde token’ın blacklist’te olup olmadığı kontrol edilir.
JWT Middleware Kullanımı (Express.js)
Token doğrulamanın her API endpoint'inde yapılması yerine, bir middleware ile merkezi hale getirilebilir:
function authenticateJWT(req, res, next) { const authHeader = req.headers.authorization; if (authHeader) { const token = authHeader.split(' ')[1]; jwt.verify(token, secretKey, (err, user) => { if (err) { return res.sendStatus(403); } req.user = user; next(); }); } else { res.sendStatus(401); } }
Bu middleware, korumak istediğiniz rotalarda kullanılabilir:
app.get('/dashboard', authenticateJWT, (req, res) => { res.send('Dashboard verileriniz'); });
JWT ile Yetkilendirme (Authorization)
JWT payload içinde kullanıcının rol bilgilerini ekleyerek yetkilendirme işlemini yapabilirsiniz.
Örneğin Token Payload:
{ "id": 1, "username": "user1", "role": "admin" }
Middleware seviyesinde basit bir kontrol:
function authorizeRole(role) { return (req, res, next) => { if (req.user.role !== role) { return res.sendStatus(403); } next(); }; }
Kullanım:
app.get('/admin', authenticateJWT, authorizeRole('admin'), (req, res) => { res.send('Admin paneli'); });
JWT’nin Avantajları
- Sunucu tarafında oturum saklamaya gerek yoktur.
- Mikroservis mimarilerinde, stateless şekilde erişim yönetimi sağlar.
- Token taşınabilir ve farklı kaynaklarda güvenli şekilde kullanılabilir.
JWT’nin Sınırlamaları
- Token süresince erişim geçerliliği devam eder. Böylece token çalınırsa kötüye kullanılabilir.
- Blacklist yapılandırması ekstra kaynak tüketir.
- Kaybolan ya da süresi dolan refresh token'ların yönetimi zordur.
Sonuç
JWT ile kimlik doğrulama, modern web servislerinin güvenliğini sağlamak için oldukça etkili bir yöntemdir. Özellikle durumsuz mimariye sahip sistemlerde sade ve performanslı bir çözüm sunar. Ancak güvenlik önlemleri ve token yönetimi doğru uygulanmazsa ciddi açıklar oluşabilir. Bu nedenle access/refresh token ayrımını doğru yapmak, HTTPS kullanmak, blacklist stratejilerini uygulamak gereklidir.