✅ JavaScript ile JWT Oluşturma: Güvenli Kimlik Doğrulamanın Temelleri
🔰 Giriş: JSON Web Token (JWT) Nedir?
JWT (JSON Web Token), web uygulamalarında kullanıcı doğrulama ve bilgi aktarımı için kullanılan açık bir standarttır. Özellikle kullanıcının kimliğini güvenli şekilde doğrulamak, oturum yönetmek ve API güvenliği sağlamak amacıyla tercih edilir.
JWT, üç parçadan oluşan, imzalanmış bir metin dizesidir:
CopyEditeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VybmFtZSI6ImFsaSIsInJvbGUiOiJ1c2VyIn0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
📦 JWT Yapısı
JWT üç ana bölümden oluşur:
- Header (Başlık): Algoritma ve token türünü belirtir.
- Payload (Yük): Kullanıcı bilgileri ve özel veriler bulunur.
- Signature (İmza): Header + Payload + Secret Key üzerinden hesaplanır.
🚀 Neden JWT Kullanmalıyız?
- ✅ Oturum yönetimini stateless (sunucusuz) hale getirir.
- 🔐 Bilgiler güvenli şekilde iletilir.
- 🌐 API ve mikro servisler arasında kolay taşınabilir.
- 🧪 Hızlı doğrulama yapılabilir.
🛠️ JavaScript ile JWT Oluşturma: Uygulamalı Kod Örneği
1. jsonwebtoken
Kütüphanesini Kurun
bashCopyEditnpm install jsonwebtoken
2. Basit JWT Oluşturma Örneği
javascriptCopyEditconst jwt = require('jsonwebtoken');
const kullanici = {
id: 1,
username: 'ornekKullanici',
rol: 'admin'
};
const secretKey = 'gizliAnahtar';
const token = jwt.sign(kullanici, secretKey, { expiresIn: '2h' });
console.log("JWT Token:", token);
📌 Açıklama:
jwt.sign()
fonksiyonu ile token oluşturulur.expiresIn
ile geçerlilik süresi ayarlanır.secretKey
, sadece sunucu tarafından bilinir.
🔎 JWT Decode Etme (İçeriğini Okuma)
javascriptCopyEditconst decoded = jwt.decode(token);
console.log(decoded);
Bu işlem doğrulama yapmadan sadece payload’ı gösterir. Güvenlik kontrolü için verify() kullanılmalıdır.
🔐 JWT Doğrulama (Verify)
javascriptCopyEdittry {
const dogrulanmis = jwt.verify(token, secretKey);
console.log("Doğrulandı:", dogrulanmis);
} catch (err) {
console.log("Token geçersiz veya süresi dolmuş.");
}
🧱 Express.js API ile JWT Kullanımı
1. Token Üretme Endpoint’i
javascriptCopyEditapp.post('/login', (req, res) => {
const { username, password } = req.body;
if (username === 'admin' && password === '1234') {
const token = jwt.sign({ username }, secretKey, { expiresIn: '1h' });
res.json({ token });
} else {
res.status(401).json({ mesaj: 'Hatalı giriş!' });
}
});
2. Korunan Route
javascriptCopyEditfunction tokenKontrol(req, res, next) {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.status(403).json({ mesaj: 'Token yok!' });
jwt.verify(token, secretKey, (err, decoded) => {
if (err) return res.status(401).json({ mesaj: 'Geçersiz token!' });
req.kullanici = decoded;
next();
});
}
app.get('/gizli', tokenKontrol, (req, res) => {
res.json({ mesaj: `Hoş geldin ${req.kullanici.username}` });
});
🧠 JWT Kullanım Alanları
Alan | Açıklama |
---|---|
🔑 Kimlik Doğrulama | Login olan kullanıcıya token verilir |
🌐 API Güvenliği | Her istekte token doğrulaması yapılır |
📱 Mobil Uygulamalar | Backend ile güvenli iletişim sağlanır |
🧩 Mikro servisler | Servisler arası kimlik doğrulaması |
🔒 Role-based access | Token’a rol bilgisi eklenerek yetki kontrolü yapılır |
💥 Yaygın JWT Hataları ve Güvenlik İpuçları
⚠️ Hatalar
- Token’ı istemcide düz metinle saklamak (örneğin
localStorage
) - Süresiz token oluşturmak
- Secret key’in zayıf olması
✅ Güvenlik İpuçları
- HTTPS olmadan asla JWT gönderme
- Token süresi kısa tut
- Secret key’i güçlü seç
- Refresh token mekanizması kullan
- Role & izinleri token içinde tut
📊 JWT ve Cookie / Session Karşılaştırması
Özellik | JWT | Session/Cookie |
---|---|---|
Saklama | İstemci | Sunucu (session) |
Statik | Stateless | Stateful |
Hız | Hızlı | Göreceli yavaş |
Taşınabilirlik | Yüksek | Düşük |
Güvenlik | Secret Key gerekli | Oturum yönetimi |
🔁 Refresh Token Kullanımı
🔍 Neden Refresh Token Gerekir?
Access token’lar kısa süreli tutulduğunda (örneğin 15 dakika), kullanıcı deneyimini bozmadan oturumu devam ettirmek için refresh token kullanılır.
🛠 Refresh Token Örneği
1. Giriş (Login) Anında Hem Access Hem Refresh Token Üret:
javascriptCopyEditconst jwt = require('jsonwebtoken');
const kullanici = { id: 1, username: "admin" };
const accessToken = jwt.sign(kullanici, secretKey, { expiresIn: '15m' });
const refreshToken = jwt.sign(kullanici, refreshSecretKey, { expiresIn: '7d' });
res.json({
accessToken,
refreshToken
});
2. Refresh Token ile Yeni Access Token Üret:
javascriptCopyEditapp.post('/token', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) return res.sendStatus(401);
jwt.verify(refreshToken, refreshSecretKey, (err, user) => {
if (err) return res.sendStatus(403);
const yeniAccessToken = jwt.sign({ username: user.username }, secretKey, { expiresIn: '15m' });
res.json({ accessToken: yeniAccessToken });
});
});
🧰 JWT İle Yetkilendirme (Authorization)
JWT içerisine kullanıcı rolü eklenerek farklı seviyelerde erişim sağlanabilir.
Kod Örneği:
javascriptCopyEditconst token = jwt.sign({
id: 5,
username: 'ali',
role: 'admin'
}, secretKey, { expiresIn: '1h' });
Yetkilendirme Kontrolü:
javascriptCopyEditapp.get('/admin', tokenKontrol, (req, res) => {
if (req.kullanici.role !== 'admin') return res.status(403).json({ mesaj: 'Yetkisiz' });
res.send("Yönetici paneline hoş geldiniz.");
});
⚙️ JWT Saklama Yöntemleri
Yöntem | Açıklama | Güvenlik |
---|---|---|
localStorage | Kolay erişim ama XSS riski yüksek | ❌ |
sessionStorage | Sekmeye özel, daha güvenli | ⚠️ |
HttpOnly Cookie | JS erişemez, XSS’e karşı korumalı | ✅ |
👉 En güvenli yöntem: HttpOnly
ve Secure
flag’li cookie kullanımıdır.
📌 JWT Kullanırken Dikkat Edilmesi Gerekenler
- Token blacklist mekanizması kullan.
- Uzun süreli refresh token’ları belirli aralıklarla yenile.
- Token id’si (
jti
) kullanarak her token’ı benzersiz hale getir. - Kullanıcı çıkış yaptığında refresh token’ı sunucudan sil.
🧪 Gerçek Hayatta JWT Kullanım Senaryoları
1. SPA (Single Page Application) Projeleri
Vue, React, Angular gibi frontend frameworkleriyle JWT mükemmel çalışır.
2. Mobil Uygulamalar
Android/iOS uygulamalarında backend ile iletişimde token kullanımı önerilir.
3. Mikroservis Mimarisi
Farklı servislerin birbiriyle iletişiminde merkezi kimlik doğrulama sağlar.
🌍 JWT ile OAuth 2.0 Entegrasyonu
JWT, OAuth 2.0 protokolüyle birlikte kullanılarak sosyal girişlerde (Google, Facebook, GitHub vs.) kullanıcı kimliği taşınabilir hale gelir.
📘 Faydalı Kaynaklar
📚 Eğitim ve Kurs Önerileri
Platform | Kurs | Seviye |
---|---|---|
Udemy | “Node.js REST API with JWT Authentication” | Orta |
Coursera | “Web Security Fundamentals” | Başlangıç |
YouTube | Traversy Media – JWT Crash Course | Orta |
Medium | JSON Web Tokens 101 Makale Serisi | Başlangıç-Orta |
🚀 Uçtan Uca JWT Kimlik Doğrulama Sistemi
🎯 Hedef
- Kayıt (register)
- Giriş (login)
- Token doğrulama (middleware)
- Korunan rota (authenticated route)
- Çıkış (logout)
- Refresh token sistemi
📁 Proje Yapısı
luaCopyEditjwt-auth/
│
├── controllers/
│ └── authController.js
├── middlewares/
│ └── authMiddleware.js
├── routes/
│ └── authRoutes.js
├── app.js
├── config.js
└── package.json
⚙️ Gerekli Kurulumlar
bashCopyEditnpm init -y
npm install express jsonwebtoken dotenv
.env
dosyasına:
envCopyEditACCESS_SECRET=supersecretaccesstoken
REFRESH_SECRET=supersecretrefreshtoken
📄 app.js
javascriptCopyEditconst express = require('express');
const app = express();
const authRoutes = require('./routes/authRoutes');
app.use(express.json());
app.use('/api/auth', authRoutes);
app.listen(3000, () => {
console.log("Sunucu 3000 portunda çalışıyor");
});
🧩 routes/authRoutes.js
javascriptCopyEditconst express = require('express');
const router = express.Router();
const { login, register, refreshToken, protectedRoute } = require('../controllers/authController');
const verifyToken = require('../middlewares/authMiddleware');
router.post('/register', register);
router.post('/login', login);
router.post('/token', refreshToken);
router.get('/dashboard', verifyToken, protectedRoute);
module.exports = router;
🧠 controllers/authController.js
javascriptCopyEditconst jwt = require('jsonwebtoken');
const users = []; // Sahte kullanıcı veritabanı
const register = (req, res) => {
const { username, password } = req.body;
users.push({ username, password });
res.json({ message: "Kayıt başarılı" });
};
const login = (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);
if (!user) return res.status(401).json({ message: 'Kullanıcı bulunamadı' });
const accessToken = jwt.sign({ username }, process.env.ACCESS_SECRET, { expiresIn: '15m' });
const refreshToken = jwt.sign({ username }, process.env.REFRESH_SECRET, { expiresIn: '7d' });
res.json({ accessToken, refreshToken });
};
const refreshToken = (req, res) => {
const { token } = req.body;
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.REFRESH_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
const newAccessToken = jwt.sign({ username: user.username }, process.env.ACCESS_SECRET, { expiresIn: '15m' });
res.json({ accessToken: newAccessToken });
});
};
const protectedRoute = (req, res) => {
res.json({ message: "Gizli bilgi: JWT ile erişildi!" });
};
module.exports = { register, login, refreshToken, protectedRoute };
🛡️ middlewares/authMiddleware.js
javascriptCopyEditconst jwt = require('jsonwebtoken');
const verifyToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(" ")[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.ACCESS_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
module.exports = verifyToken;
🖥️ Postman Test Senaryoları
İşlem | HTTP | Endpoint | Açıklama |
---|---|---|---|
Kayıt | POST | /api/auth/register | Yeni kullanıcı oluşturur |
Giriş | POST | /api/auth/login | Access ve refresh token döner |
Token yenile | POST | /api/auth/token | Refresh token ile yeni access alınır |
Koruma | GET | /api/auth/dashboard | Sadece geçerli token ile erişilir |
🧑💻 React ile JWT Kimlik Doğrulama – Frontend Entegrasyonu
🧱 1. React Projesi Kurulumu
bashCopyEditnpx create-react-app jwt-auth-client
cd jwt-auth-client
npm install axios react-router-dom
📁 Proje Dosya Yapısı
pgsqlCopyEditsrc/
│
├── components/
│ ├── Login.js
│ ├── Register.js
│ ├── Dashboard.js
│
├── services/
│ └── authService.js
│
├── App.js
└── index.js
🔐 authService.js – Token İşlemleri
javascriptCopyEditimport axios from "axios";
const API_URL = "http://localhost:3000/api/auth/";
export const register = async (user) => {
return await axios.post(API_URL + "register", user);
};
export const login = async (user) => {
const res = await axios.post(API_URL + "login", user);
if (res.data.accessToken) {
localStorage.setItem("accessToken", res.data.accessToken);
localStorage.setItem("refreshToken", res.data.refreshToken);
}
return res.data;
};
export const getProtected = async () => {
const token = localStorage.getItem("accessToken");
return await axios.get(API_URL + "dashboard", {
headers: { Authorization: `Bearer ${token}` },
});
};
📝 Register.js – Kayıt Sayfası
javascriptCopyEditimport { useState } from "react";
import { register } from "../services/authService";
function Register() {
const [form, setForm] = useState({ username: "", password: "" });
const handleSubmit = async (e) => {
e.preventDefault();
await register(form);
alert("Kayıt başarılı!");
};
return (
<form onSubmit={handleSubmit}>
<h2>Kayıt Ol</h2>
<input type="text" placeholder="Kullanıcı Adı"
onChange={(e) => setForm({ ...form, username: e.target.value })} />
<input type="password" placeholder="Şifre"
onChange={(e) => setForm({ ...form, password: e.target.value })} />
<button type="submit">Kayıt</button>
</form>
);
}
export default Register;
🔐 Login.js – Giriş Sayfası
javascriptCopyEditimport { useState } from "react";
import { login } from "../services/authService";
function Login() {
const [form, setForm] = useState({ username: "", password: "" });
const handleSubmit = async (e) => {
e.preventDefault();
const data = await login(form);
alert(`Hoş geldin ${data.username}`);
};
return (
<form onSubmit={handleSubmit}>
<h2>Giriş Yap</h2>
<input type="text" placeholder="Kullanıcı Adı"
onChange={(e) => setForm({ ...form, username: e.target.value })} />
<input type="password" placeholder="Şifre"
onChange={(e) => setForm({ ...form, password: e.target.value })} />
<button type="submit">Giriş</button>
</form>
);
}
export default Login;
🔒 Dashboard.js – Korunan Sayfa
javascriptCopyEditimport { useEffect, useState } from "react";
import { getProtected } from "../services/authService";
function Dashboard() {
const [secret, setSecret] = useState("");
useEffect(() => {
getProtected().then(res => setSecret(res.data.message));
}, []);
return (
<div>
<h2>Gizli Bilgi</h2>
<p>{secret}</p>
</div>
);
}
export default Dashboard;
🚦 App.js – Yönlendirme
javascriptCopyEditimport { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Register from "./components/Register";
import Login from "./components/Login";
import Dashboard from "./components/Dashboard";
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Router>
);
}
export default App;
🔐 Güvenlik Notları
- Token’ı
localStorage
yerinehttpOnly cookie
ile saklamak daha güvenlidir. - Refresh token sistemi ile token süresi bitince yeniden login olmadan güncellenmesi sağlanabilir.
- CORS ayarları backend tarafında yapılmalıdır.
- HTTPS kullanımı zorunludur (özellikle production’da).
Review JavaScript ile JWT Oluşturma: Güvenli Kimlik Doğrulamanın Temelleri.