Merhaba arkadaşlar, bugün başımı çok ağrıtan bir konudan bahsedeceğim: JWT token'larını nereye saklamalı? Projelerimde uzun süre localStorage kullandım ve "zaten HTTPS var, sıkıntı yok" diye düşündüm. Ta ki, XSS (Cross-Site Scripting) saldırılarının ne kadar kolay token'ı çalabildiğini görünceye kadar. O gün, token güvenliği konusunda bildiğim her şeyi yeniden düşünmek zorunda kaldım.
Karşılaştığım Sorun
Bir kullanıcı şikayeti üzerine araştırma yaparken, sitenin yorum bölümüne basit bir script etiketi eklenebildiğini fark ettim. Bu script, sayfadaki tüm localStorage verilerini, içindeki JWT token'ı da alıp uzak bir sunucuya gönderebiliyordu. İşte o an, localStorage'ın XSS'e karşı tamamen savunmasız olduğunu somut olarak gördüm ve kafayı yemiştim. Token çalınınca, saldırgan kullanıcının kimliğine bürünüp tüm işlemleri yapabilirdi.
HttpOnly Cookie Çözümü
Araştırmalarım beni HttpOnly Cookie kullanımına yöneltti. Bu yöntemde, token sunucu tarafından bir cookie olarak ayarlanır ve bu cookie'ye yalnızca sunucu erişebilir. JavaScript ile okunamaz, dolayısıyla XSS saldırılarından etkilenmez.
İşte backend'de (Node.js + Express örneği) token'ı HttpOnly cookie olarak nasıl gönderdiğim:
Frontend tarafında ise artık token'ı manuel olarak request header'ına eklememe gerek kalmadı. Tarayıcı, her istekte bu cookie'yi otomatik olarak sunucuya gönderiyor.
İki Yöntemin Artıları ve Eksileri
LocalStorage/ SessionStorage:
Artıları: Kullanımı kolay, JavaScript ile tam kontrol.
Eksileri: XSS saldırılarına AÇIK. Token'ı elle header'a eklemek gerekir.
HttpOnly Cookies:
Artıları: XSS'e karşı ÇOK DAHA GÜVENLİ. Tarayıcı otomatik yönetir.
Eksileri: CSRF (Cross-Site Request Forgery) saldırılarına karşı dikkatli olunmalı (SameSite=Strict ile korunur). Frontend'den JavaScript ile okunamaz.
CSRF Koruması Nasıl Sağladım?
HttpOnly Cookie kullanınca akla ilk gelen risk CSRF. Bunun için SameSite=Strict attribute'unu kullanıyorum (yukarıdaki kodda mevcut). Ayrıca, kritik işlemler (şifre değiştirme, ödeme vs.) için sunucu tarafında ek bir CSRF token doğrulaması da uygulayabilirsiniz. Modern tarayıcılarda SameSite attribute'u büyük ölçüde yeterli koruma sağlıyor.
Sonuç olarak, güvenlik önceliğim olduğu için artık neredeyse tüm projelerimde JWT token'larını HttpOnly, Secure, SameSite Strict Cookie olarak saklıyorum. Bu değişiklikten sonra XSS kaynaklı güvenlik endişelerim büyük ölçüde azaldı.
Peki ya siz? Token saklama konusunda hangi yöntemi tercih ediyorsunuz? HttpOnly cookie kullanırken karşılaştığınız farklı zorluklar oldu mu? Ya da SPA (Single Page Application) yapılarında bu yaklaşımı nasıl buldunuz? Yorumlarda deneyimlerinizi paylaşın, tartışalım!
Bir kullanıcı şikayeti üzerine araştırma yaparken, sitenin yorum bölümüne basit bir script etiketi eklenebildiğini fark ettim. Bu script, sayfadaki tüm localStorage verilerini, içindeki JWT token'ı da alıp uzak bir sunucuya gönderebiliyordu. İşte o an, localStorage'ın XSS'e karşı tamamen savunmasız olduğunu somut olarak gördüm ve kafayı yemiştim. Token çalınınca, saldırgan kullanıcının kimliğine bürünüp tüm işlemleri yapabilirdi.
Araştırmalarım beni HttpOnly Cookie kullanımına yöneltti. Bu yöntemde, token sunucu tarafından bir cookie olarak ayarlanır ve bu cookie'ye yalnızca sunucu erişebilir. JavaScript ile okunamaz, dolayısıyla XSS saldırılarından etkilenmez.
İşte backend'de (Node.js + Express örneği) token'ı HttpOnly cookie olarak nasıl gönderdiğim:
JavaScript:
const jwt = require('jsonwebtoken');
app.post('/api/login', (req, res) => {
// Kullanıcı doğrulaması yapılır...
const user = { id: 123, email: 'ornek@bingunluk.com' };
// JWT token oluştur
const token = jwt.sign(user, process.env.JWT_SECRET, { expiresIn: '1h' });
// Token'ı HTTP Only, Secure, SameSite cookie olarak gönder
res.cookie('access_token', token, {
httpOnly: true, // JavaScript ile erişilemez
secure: process.env.NODE_ENV === 'production', // Sadece HTTPS'te çalışır
sameSite: 'strict', // CSRF saldırılarına karşı koruma
maxAge: 60 60 1000 // 1 saat
});
res.json({ message: 'Giriş başarılı!' });
});
Frontend tarafında ise artık token'ı manuel olarak request header'ına eklememe gerek kalmadı. Tarayıcı, her istekte bu cookie'yi otomatik olarak sunucuya gönderiyor.
LocalStorage/ SessionStorage:
HttpOnly Cookies:
HttpOnly Cookie kullanınca akla ilk gelen risk CSRF. Bunun için SameSite=Strict attribute'unu kullanıyorum (yukarıdaki kodda mevcut). Ayrıca, kritik işlemler (şifre değiştirme, ödeme vs.) için sunucu tarafında ek bir CSRF token doğrulaması da uygulayabilirsiniz. Modern tarayıcılarda SameSite attribute'u büyük ölçüde yeterli koruma sağlıyor.
Sonuç olarak, güvenlik önceliğim olduğu için artık neredeyse tüm projelerimde JWT token'larını HttpOnly, Secure, SameSite Strict Cookie olarak saklıyorum. Bu değişiklikten sonra XSS kaynaklı güvenlik endişelerim büyük ölçüde azaldı.
Peki ya siz? Token saklama konusunda hangi yöntemi tercih ediyorsunuz? HttpOnly cookie kullanırken karşılaştığınız farklı zorluklar oldu mu? Ya da SPA (Single Page Application) yapılarında bu yaklaşımı nasıl buldunuz? Yorumlarda deneyimlerinizi paylaşın, tartışalım!