JSON Web Tokens (JWT), modern web uygulamalarında durum bilgisi gerektirmeyen kimlik doğrulama için de facto standart haline geldi. Sunucuların her istek için veritabanına sorgu yapmadan kullanıcı kimliğini doğrulamasını sağlarlar. Ancak, bu kolaylık sıklıkla yanlış yapılandırmalara yol açarak uygulamaları ciddi güvenlik açıklarına maruz bırakır. Bu kılavuzda, temel sözdiziminin ötesine geçerek sağlam bir güvenlik mimarisine ulaşmak için JWT uygulamanızı güçlendirmeye yönelik gelişmiş stratejileri keşfedeceğiz.
1. Güçlü Algoritmalar ve Anahtarlar Seçin
JWT uygulamasındaki en kritik güvenlik kusurlarından biri, imzalama algoritmalarının yanlış seçimidir. Birçok eğitim materyali, simetrik bir anahtara dayanan HS256'yi rahatlıkla önerir. İç hizmetler için uygun olsa da, gizli anahtarın hizmetler arasında paylaşılması gereken dağıtık sistemlerde risk oluşturur. Bunun yerine, RS256 veya ES256 gibi asimetrik algoritmaları tercih edin. Bu algoritmalar, doğrulama için bir genel anahtar yayımlamanıza ve özel anahtarı sunucuda güvende tutmanıza olanak tanır.
Ayrıca, asla zayıf veya boş gizli anahtarlar kullanmayın. Her zaman kriptografik olarak güvenli bir rastgele sayı üreteci tarafından oluşturulan yüksek entropili rastgele dizeler kullanın. Aşağıda, Node.js'de RS256 için güvenli bir özel anahtar oluşturmanın bir örneği verilmiştir:
const crypto = require('crypto');
// 2048 bitlik bir RSA anahtar çifti oluştur
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
console.log(privateKey); // Bu değeri bir kasada saklayın gibi güvenli bir yerde saklayın
console.log(publicKey); // Doğrulama için istemcilere dağıtın
2. Kısa Süre Sonu Zamanlarını Zorunlu Kılın
JWT'lerin kısa bir ömür süresi olmalıdır. Uzun bir süre sonu penceresine (örneğin 24 saat veya 30 gün) sahip bir token, çalınması durumunda risk penceresini artırır. En iyi uygulama, Erişim Tokenlarını kısa ömürlü (15-30 dakika) olarak yayınlamak ve uzun süreli oturumlar için Yenileme Tokenlarını kullanmaktır. Erişim tokenları, anlık API çağrıları için kimliği kanıtlar; daha güvenli bir şekilde saklanan yenileme tokenları ise yeni erişim tokenları elde etmek için kullanılır.
const jwt = require('jsonwebtoken');
const generateAccessToken = (user) => {
return jwt.sign(
{ userId: user.id, role: user.role },
privateKey,
{
algorithm: 'RS256',
expiresIn: '15m' // Kısa ömürlü erişim tokenı
}
);
};
const generateRefreshToken = (user) => {
return jwt.sign(
{ userId: user.id },
privateKey,
{
algorithm: 'RS256',
expiresIn: '7d' // Uzun ömürlü yenileme tokenı
}
);
};
3. Token İptalini Uygulayın
JWT'ler durum bilgisi gerektirmeyen (stateless) yapıda oldukları için, süresi dolmadan önce iptal edilmeleri yerel olarak desteklenmez. Bunu aşmak için, açıkça iptal edilen tokenlar (örneğin çıkış yapma veya şifre değiştirme sırasında) için bir "karaliste" veya "engelleme listesi" uygulayabilirsiniz. Kısa ömürlü tokenlar için bu kadar kritik olmasa da, yenileme tokenları için hayati önem taşır.
Alternatif olarak, bir "jti" (JWT ID) iddiası kullanın ve yayımlanan token kimliklerini Redis gibi hızlı bir anahtar-değer deposunda saklayın. Bir isteği işlemeden önce, jti'nin depoda var olup olmadığını kontrol edin.
// İptal edilmiş tokenları kontrol etmek için sahte kod
async function isTokenRevoked(jti) {
const revoked = await redisClient.get(`revoked:${jti}`);
return revoked === 'true';
}
4. İstemci Tarafında Güvenli Depolama
JWT'yi istemci tarafında nerede sakladığınız, onu Hedefli Site Betiği (XSS) ve Hedefli Site İsteği Sahteciliği (CSRF) saldırılarına karşı ne kadar maruz bıraktığınızı belirler. Tokenları localStorage'da saklamak, tarayıcıda çalışan herhangi bir JavaScript'in bunlara erişmesini sağlar ve XSS saldırılarını kolaylaştırır. Bunun yerine, HTTP-only çerezleri kullanın. Bunlar JavaScript tarafından erişilemez olup, XSS tabanlı hırsızlığı etkili bir şekilde etkisiz hale getirir.
Çerezler kullanırken, CSRF saldırılarını önlemek için SameSite özniteliğini Strict veya Lax olarak ayarladığınızdan emin olun. Ayrıca, tokenların ara sunucu saldırıları yoluyla engellenmesini önlemek için her zaman HTTPS üzerinden iletilmesini sağlayın.
Sonuç
JWT kimlik doğrulamasını güvence altına almak tek seferlik bir kurulum değil; algoritmaları, ömür sürelerini ve depolama mekanizmalarını değerlendirmeye yönelik sürekli bir süreçtir. Güçlü asimetrik algoritmalar, kısa süre sonu zamanları, iptal stratejileri ve güvenli depolama uygulamaları uygulayarak uygulamanızın saldırı yüzeyini önemli ölçüde azaltabilirsiniz. Unutmayın, tek bir önlem kusursuz değildir; kimlik doğrulama akışınızda sağlam güvenliği korumanın anahtarı derinlemesine savunmadır.