Merhaba arkadaşlar, bugün başımı çok ağrıtan bir konuyu, özellikle de yeni başlayan arkadaşların kafasını karıştırdığını düşündüğüm bir detayı netleştirmek istiyorum. "JWT token'ımı Authorization header'ı ile gönderiyorum, ama CORS hatası almıyorum. Bu nasıl oluyor?" diye düşündüğünüz oldu mu? Ben de ilk başta "CORS, özel header'ları engellemiyor muydu?" diye kafayı yemiştim. İşin aslını anlayınca aslında çok mantıklı olduğunu gördüm.
CORS'un Temel Mantığı Nedir?
Öncelikle şunu netleştirelim: CORS (Cross-Origin Resource Sharing), tarayıcıların güvenlik için uyguladığı bir mekanizma. Sunucu tarafından kontrol edilir. Basitçe, "A" domain'inden (origin) gelen bir istek, "B" domain'indeki bir kaynağa erişmek istediğinde devreye girer. Tarayıcı, asıl istekten (GET, POST gibi) önce, sunucuya bir OPTIONS isteği (Preflight Request) atar ve "Bak kardeşim, ben şu header'ları göndereceğim, şu metodları kullanacağım, kabul ediyor musun?" diye sorar.
Karşılaştığım Kafa Karışıklığı
Benim kafamı karıştıran nokta şuydu: CORS politikaları, özel header'lar (Authorization, Content-Type gibi) gönderdiğimizde preflight isteğini tetikler ve sunucunun bu header'lara izin vermesi (Access-Control-Allow-Headers) gerekir. Peki neden JWT token gönderirken sürekli CORS hatasıyla uğraşmıyoruz? Cevap: Eğer sunucu doğru şekilde yapılandırılmışsa, zaten bu izni veriyordur!
İşin Püf Noktası: Sunucu Tarafı Yapılandırması
Sorun çıkmamasının sebebi, genellikle backend API'nizin (Laravel, Express.js, Django vs.) CORS yapılandırmasında Authorization header'ının zaten izinli header'lar listesinde (allowedHeaders) tanımlı olması. İzin verilmediği durumda zaten hatayı alırsınız. İşte Node.js (Express) için basit bir örnek:
Gördüğünüz gibi, corsOptions nesnesinin allowedHeaders kısmında 'Authorization' değeri mevcut. Bu, tarayıcının preflight isteğine sunucunun "Evet, Authorization header'ını kabul ediyorum" cevabını vermesini sağlar. Aynı ayar Laravel'de cors.php config dosyasında, Django'da ise CORS paketinin ayarlarında yapılır.
Preflight İsteği Ne Zaman Gerekmez?
Küçük bir dipnot: Bazen preflight isteği atılmaz. Eğer isteğiniz "simple request" kriterlerine uyuyorsa (belirli metodlar, belirli content-type vs.), tarayıcı doğrudan asıl isteği atar ve Authorization header'ı eklenmiş olsa bile preflight olmaz. Ancak modern uygulamalarda genellikle Content-Type: application/json kullandığımız için bu kriteri aşar ve preflight her zaman gerçekleşir. Yani güvenli tarafta kalmak için sunucunuzu her ihtimale karşı yapılandırmak en iyisi.
Sonuç olarak, JWT token gönderirken CORS hatası almamanız bir sihir değil, arka planda düzgün yapılandırılmış bir sunucunun varlığıdır. Siz backend tarafında CORS ayarlarınızı yaparken hangi paketleri veya middleware'leri kullanıyorsunuz? Laravel'de fruitcake/laravel-cors mı, yoksa Express'te cors paketini mi tercih ediyorsunuz? Hiç Authorization header'ını unuttuğunuz ve saatlerce hatanın nerede olduğunu aradığınız oldu mu? Deneyimlerinizi yorumlarda paylaşın!
Öncelikle şunu netleştirelim: CORS (Cross-Origin Resource Sharing), tarayıcıların güvenlik için uyguladığı bir mekanizma. Sunucu tarafından kontrol edilir. Basitçe, "A" domain'inden (origin) gelen bir istek, "B" domain'indeki bir kaynağa erişmek istediğinde devreye girer. Tarayıcı, asıl istekten (GET, POST gibi) önce, sunucuya bir OPTIONS isteği (Preflight Request) atar ve "Bak kardeşim, ben şu header'ları göndereceğim, şu metodları kullanacağım, kabul ediyor musun?" diye sorar.
Benim kafamı karıştıran nokta şuydu: CORS politikaları, özel header'lar (Authorization, Content-Type gibi) gönderdiğimizde preflight isteğini tetikler ve sunucunun bu header'lara izin vermesi (Access-Control-Allow-Headers) gerekir. Peki neden JWT token gönderirken sürekli CORS hatasıyla uğraşmıyoruz? Cevap: Eğer sunucu doğru şekilde yapılandırılmışsa, zaten bu izni veriyordur!
Sorun çıkmamasının sebebi, genellikle backend API'nizin (Laravel, Express.js, Django vs.) CORS yapılandırmasında Authorization header'ının zaten izinli header'lar listesinde (allowedHeaders) tanımlı olması. İzin verilmediği durumda zaten hatayı alırsınız. İşte Node.js (Express) için basit bir örnek:
JavaScript:
const express = require('express');
const cors = require('cors');
const app = express();
// CORS ayarları
const corsOptions = {
origin: 'https://guvenilir-alanadim.com', // İzin verilen origin
methods: ['GET', 'POST', 'PUT', 'DELETE'], // İzin verilen metodlar
allowedHeaders: ['Content-Type', 'Authorization'], // İzin verilen header'lar
// 'Authorization' header'ı burada tanımlı!
};
app.use(cors(corsOptions));
// API rotalarınız...
app.get('/api/protected-data', (req, res) => {
const token = req.headers['authorization']; // Token buradan okunur
// Token doğrulama işlemleri...
res.json({ data: 'Gizli veriler burada!' });
});
app.listen(3000, () => console.log('Sunucu 3000 portunda çalışıyor.'));
Gördüğünüz gibi, corsOptions nesnesinin allowedHeaders kısmında 'Authorization' değeri mevcut. Bu, tarayıcının preflight isteğine sunucunun "Evet, Authorization header'ını kabul ediyorum" cevabını vermesini sağlar. Aynı ayar Laravel'de cors.php config dosyasında, Django'da ise CORS paketinin ayarlarında yapılır.
Küçük bir dipnot: Bazen preflight isteği atılmaz. Eğer isteğiniz "simple request" kriterlerine uyuyorsa (belirli metodlar, belirli content-type vs.), tarayıcı doğrudan asıl isteği atar ve Authorization header'ı eklenmiş olsa bile preflight olmaz. Ancak modern uygulamalarda genellikle Content-Type: application/json kullandığımız için bu kriteri aşar ve preflight her zaman gerçekleşir. Yani güvenli tarafta kalmak için sunucunuzu her ihtimale karşı yapılandırmak en iyisi.
Sonuç olarak, JWT token gönderirken CORS hatası almamanız bir sihir değil, arka planda düzgün yapılandırılmış bir sunucunun varlığıdır. Siz backend tarafında CORS ayarlarınızı yaparken hangi paketleri veya middleware'leri kullanıyorsunuz? Laravel'de fruitcake/laravel-cors mı, yoksa Express'te cors paketini mi tercih ediyorsunuz? Hiç Authorization header'ını unuttuğunuz ve saatlerce hatanın nerede olduğunu aradığınız oldu mu? Deneyimlerinizi yorumlarda paylaşın!