JWT Nedir? 20 Dakikada Güvenli Kimlik Doğrulama
JWT ile modern kimlik doğrulamayı öğrenin: token yapısı, güvenlik riskleri, refresh token akışı ve Node.js örneğiyle adım adım uygulayın.
JWT Nedir? 20 Dakikada Güvenli Kimlik Doğrulama
Meta Description
JWT nedir ve nasıl kullanılır? Access/refresh token akışı, güvenlik ipuçları ve Node.js örneğiyle 20 dakikada uygulayın.
Giriş (Introduction)
Bir API geliştiriyorsunuz, mobil uygulama veya SPA (React/Vue) ile konuşuyor… Peki kullanıcı giriş yaptıktan sonra istekleri nasıl güvenli şekilde yetkilendireceksiniz? “Session mı kullanmalıyım, token mı?” sorusu burada başlar.
JWT (JSON Web Token), modern uygulamalarda kimlik doğrulama ve yetkilendirme için en yaygın yaklaşımlardan biri. Doğru uygulandığında hızlı ve ölçeklenebilir; yanlış uygulandığında ise token çalınması, uzun süreli erişim ve hesap ele geçirme gibi riskler doğurabilir.
Bu yazıda JWT’nin mantığını, access token / refresh token akışını ve gerçek hayatta doğru konfigürasyonla nasıl uygulanacağını adım adım öğreneceksiniz.
JWT Nedir? (Ana Anahtar Kelime)
JWT, sunucu ile istemci arasında taşınan, içinde JSON veri barındıran ve imzalanmış bir token formatıdır. En sık kullanım şekli:
- Kullanıcı giriş yapar
- Sunucu bir JWT access token üretir
- İstemci sonraki isteklerde
Authorization: Bearer <token>ile bu token’ı gönderir
Bunu neden yapmalıyım?
- API’lerde stateless (durumsuz) çalışmayı kolaylaştırır
- Mikro servis ve ölçeklenebilir mimarilerde pratik bir çözümdür
- Mobil/SPA gibi istemcilerle uyumludur
Not: JWT tek başına “güvenlik” değildir. Güvenlik, doğru süreler, doğru saklama ve doğru doğrulama ile gelir.
JWT Yapısı: Header, Payload, Signature
JWT genelde şu formattadır:
xxxxx.yyyyy.zzzzz
| Bölüm | Ne içerir? | Örnek |
|---|---|---|
| Header | Algoritma ve token tipi | {"alg":"HS256","typ":"JWT"} |
| Payload | İddialar (claims) | {"sub":"123","role":"admin","exp":...} |
| Signature | İmza | Header+Payload + secret/private key |
Payload’da hangi bilgiler olmalı?
- Minimal veri:
sub(user id),role/scope,expgibi - Kritik kişisel verileri (TC, e-posta, adres vb.) payload’a koymayın
Önemli: JWT payload’u şifreli değildir, sadece base64url ile kodlanır. Yani token’ı gören payload’u okuyabilir.
Access Token vs Refresh Token: Doğru Akış
JWT kullanırken en çok yapılan hata: çok uzun süreli access token üretmek.
Önerilen pratik yaklaşım
- Access Token: kısa ömür (5–15 dk)
- Refresh Token: daha uzun ömür (7–30 gün) ve sunucu tarafında kontrol (DB/Redis)
Akış (özet)
- Kullanıcı giriş yapar → access + refresh token alır
- İstemci API çağrılarında access token kullanır
- Access token süresi dolunca
/auth/refreshçağrılır - Sunucu refresh token geçerliyse yeni access token üretir
Bunu neden yapmalıyım?
- Access token çalınsa bile etkisi kısa sürer
- Refresh token’ı iptal ederek oturumu sunucu tarafında sonlandırabilirsiniz
JWT Güvenliği: En Sık Hatalar ve Önlemler
Aşağıdaki maddeler, Türkiye’de ekiplerin en sık takıldığı gerçek problemlerden.
1) Token’ı localStorage’da saklamak
- XSS açığında token kolayca çalınır
- Öneri: Refresh token’ı HttpOnly + Secure cookie ile saklayın
2) alg=none veya yanlış algoritma doğrulaması
- Kütüphaneyi doğru kullanın, algoritmayı kısıtlayın
3) Çok uzun token süresi
- 1 yıl geçerli access token = büyük risk
4) Logout çalışmıyor sanmak
JWT stateless olduğu için tek başına “logout” sunucu tarafında token’ı yok etmez.
- Çözüm: Refresh token’ı server-side listede tutup iptal edin (revocation)
5) Audience/Issuer kontrolü yapmamak
iss(issuer) veaud(audience) doğrulaması kritik olabilir (özellikle çoklu servislerde)
Node.js (Express) ile JWT: Adım Adım Uygulama
Aşağıdaki örnek, pratik bir başlangıç iskeleti sunar. (Prod’da ek sertleştirme gerekir.)
1) Kurulum
npm i express jsonwebtoken cookie-parser bcrypt
2) Token üretimi (access + refresh)
import jwt from "jsonwebtoken";
const ACCESS_TTL = "10m";
const REFRESH_TTL = "14d";
export function signAccessToken(user) {
return jwt.sign(
{ sub: user.id, role: user.role },
process.env.JWT_ACCESS_SECRET,
{ expiresIn: ACCESS_TTL, issuer: "my-api", audience: "my-app" }
);
}
export function signRefreshToken(user) {
return jwt.sign(
{ sub: user.id, type: "refresh" },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: REFRESH_TTL, issuer: "my-api", audience: "my-app" }
);
}
3) Middleware: Access token doğrulama
import jwt from "jsonwebtoken";
export function requireAuth(req, res, next) {
const header = req.headers.authorization;
const token = header?.startsWith("Bearer ") ? header.slice(7) : null;
if (!token) return res.status(401).json({ message: "Token gerekli" });
try {
const payload = jwt.verify(token, process.env.JWT_ACCESS_SECRET, {
issuer: "my-api",
audience: "my-app",
algorithms: ["HS256"],
});
req.user = { id: payload.sub, role: payload.role };
next();
} catch (err) {
return res.status(401).json({ message: "Geçersiz/expired token" });
}
}
4) Login endpoint (cookie ile refresh token)
import express from "express";
import cookieParser from "cookie-parser";
import { signAccessToken, signRefreshToken } from "./tokens.js";
const app = express();
app.use(express.json());
app.use(cookieParser());
app.post("/auth/login", async (req, res) => {
const { email, password } = req.body;
// Demo: kullanıcı doğrulama kısmı (DB + bcrypt) burada olmalı
const user = { id: "u_123", role: "admin", email };
const accessToken = signAccessToken(user);
const refreshToken = signRefreshToken(user);
// Öneri: refresh token'ı DB/Redis'te saklayın (rotasyon/revocation için)
res.cookie("refresh_token", refreshToken, {
httpOnly: true,
secure: true,
sameSite: "strict",
path: "/auth/refresh",
maxAge: 14 * 24 * 60 * 60 * 1000,
});
res.json({ accessToken });
});
5) Refresh endpoint (yeni access token)
import jwt from "jsonwebtoken";
app.post("/auth/refresh", (req, res) => {
const token = req.cookies.refresh_token;
if (!token) return res.status(401).json({ message: "Refresh token yok" });
try {
const payload = jwt.verify(token, process.env.JWT_REFRESH_SECRET, {
issuer: "my-api",
audience: "my-app",
algorithms: ["HS256"],
});
if (payload.type !== "refresh") {
return res.status(401).json({ message: "Yanlış token tipi" });
}
// Öneri: token DB/Redis'te geçerli mi kontrol edin (revocation)
const user = { id: payload.sub, role: "admin" }; // DB'den okunmalı
const newAccessToken = signAccessToken(user);
res.json({ accessToken: newAccessToken });
} catch (err) {
return res.status(401).json({ message: "Refresh token geçersiz/expired" });
}
});
Gerçek Hayat Senaryosu: SaaS Panelinde JWT Neden Kritik?
Diyelim ki bir SaaS admin paneliniz var:
- Kullanıcılar gün boyu panelde kalıyor
- Arka planda onlarca API çağrısı yapılıyor
- Bir XSS açığı veya cihaz kaybı yaşanabiliyor
Bu senaryoda:
- Kısa ömürlü access token ile risk daralır
- HttpOnly cookie ile refresh token’ın çalınması zorlaşır
- Refresh token rotasyonu + iptal listesi ile hesabı hızlıca güvene alırsınız
Hızlı kontrol listesi
- Access token 5–15 dk
- Refresh token HttpOnly+Secure cookie
- Refresh token server-side saklanıyor (DB/Redis)
-
iss/auddoğrulanıyor - Algoritma kısıtlı (ör. HS256)
- HTTPS zorunlu
JWT Alternatifleri: Ne Zaman JWT Kullanmayayım?
JWT her projeye şart değil.
| İhtiyaç | Daha uygun seçenek |
|---|---|
| Klasik web (SSR) ve basit auth | Session + server-side store |
| Kurumsal SSO | OAuth2 / OIDC (Keycloak, Auth0 vb.) |
| Çok servisli yetkilendirme | OIDC + kısa ömürlü token + merkezi yetki |
Bunu neden bilmeliyim? Yanlış araç seçimi, bakım maliyetini artırır ve güvenliği düşürür.
Sık Sorulan Sorular (FAQ)
1) JWT nedir ve ne işe yarar?
JWT, kullanıcı kimliğini/rollerini taşıyan imzalı bir token formatıdır. API’lerde kimlik doğrulama ve yetkilendirmede kullanılır.
2) JWT güvenli mi?
Doğru süreler, doğru saklama (özellikle refresh token için HttpOnly cookie) ve doğru doğrulama yaparsanız güvenlidir. Payload’un şifreli olmadığını unutmayın.
3) JWT ile logout nasıl yapılır?
Access token stateless olduğu için bekleyip süresinin dolması gerekir. Pratikte refresh token’ı iptal ederek logout uygulanır.
4) Access token süresi kaç olmalı?
Genellikle 5–15 dakika iyi bir dengedir. Daha uzunu risk, daha kısası kullanıcı deneyimi maliyeti doğurur.
5) JWT mi session mı daha iyi?
SPA/mobil + API için JWT pratik olur. SSR ve klasik web uygulamalarında session daha basit ve kontrollü olabilir.
Sonuç
JWT nedir sorusunun cevabı sadece “token” değil; doğru tasarlanmış bir kimlik doğrulama akışı. Bu yazıda JWT yapısını, access/refresh token mantığını, güvenlik hatalarını ve Node.js ile uygulanabilir bir örneği gördünüz.
Siz hangi mimaride JWT kullanıyorsunuz: SPA, mobil, mikro servis? Yorumlarda yazın; kullandığınız akışa göre süre/depoma stratejisi için öneri paylaşabilirim. İsterseniz bir sonraki adım olarak refresh token rotasyonu ve revocation (iptal) modeli için de örnek şablon çıkaralım.