Tüm yazılar
24 Ağustos 20263 dk okuma

Üretimde Next.js ve Supabase Kimlik Doğrulama

Yerelde çalışıp üretimde bozulan kimlik doğrulamanın suçlusu genelde kütüphane değil. Oturumun yaşadığı yer ile kodun çalıştığı yer arasındaki sınır.

Aldığım her Next.js projesi eninde sonunda aynı öğleden sonraya varıyor: kimlik doğrulama yerelde çalışıyor, önizlemede çalışıyor, sonra üretimde açıklanamaz bir şey yapıyor. Genelde suçlu auth kütüphanesi değil. Oturumun yaşadığı yer ile kodun çalıştığı yer arasındaki sınır.

Arkasında Supabase olan sekiz Next.js ürünü yayına aldım. Aşağıdakiler artık varsayılan olarak yaptığım şeyler ve her birinin var olma sebebi.

Oturum bir çerezde yaşıyor, çerezlerin kuralları var

Supabase bir JWT veriyor. Yalnızca tarayıcıda çalışan bir uygulamada bu local storage'da durur ve başka kimsenin bilmesi gerekmez. Server Component'leri işin içine kattığınız anda bu bozulur: sunucu, istemci kodu çalışmadan önce render eder, yani oturuma istek anında ihtiyacı vardır. Bu da çerez demektir.

Karışıklığın çoğu buradan çıkıyor. Middleware çerezi tazeliyor, Server Component'ler okuyor, Client Component'ler hidrasyonla alıyor. Üç yer, tek token; herhangi biri diğeriyle anlaşamazsa tarayıcıya göre giriş yapmış, sunucuya göre anonim bir kullanıcı elde edersiniz.

Uyduğum kural: doğrunun kaynağı her zaman sunucudur. İstemci durumu render için bir kolaylıktır, karar vermek için asla.

Sunucuda getSession'a güvenmeyin

Bu maddenin bedeli gerçek bir güvenlik açığı ve zararsız görünüyor.

getSession çerezi okur ve çözer. Auth sunucusuna karşı doğrulamaz. İstemcide sorun değil, çünkü istemci zaten güvenilmez ve veri kullanıcının kendisine ait. Sunucuda ise çözülmüş bir token'ı doğrulanmış saymak demek.

Sunucuda getUser kullanın. Bir gidiş dönüş maliyeti var. O gidiş dönüş zaten doğrulamanın kendisi. Bir kişinin neyi görebileceğine karar veren her kod yolu onun arkasında olmalı.

Satır seviyesi güvenlik yetkilendirme katmanıdır, yedeği değil

Supabase'de insanı çeken şey, izinleri route handler'da kontrol etmek, çünkü mantığı orada görebiliyorsunuz. İkinci bir kod yolu aynı tabloya ulaşıp unutana kadar da çalışır.

Politikayı veritabanına yazın. O zaman kontrol route'a değil veriye iliştirilmiş olur ve tabloya dokunan her yol onu miras alır: API'niz, Server Component'iniz, bir arka plan işi, handler'ınızı hiç okumamış birinin ileride yazacağı bir uç nokta.

Kullandığım pratik test: bütün route dosyalarını silsem veri hâlâ korunur mu? Cevap hayırsa politika yanlış yerde.

Middleware tazelemek içindir, korumak için değil

Middleware eşleşen her istekte çalışır, yani oturum çerezini canlı tutmak için doğal yerdir. Erişimi zorlamak için kötü bir yerdir.

İki sebep. Edge'de, veritabanınız olmadan çalışır; dolayısıyla asıl önemli soruyu, yani bu kullanıcının tam olarak neye izinli olduğunu soramaz. Bir de middleware'den yapılan yönlendirme bir rota kararıdır, güvenlik sınırı değil: verinize başka bir yoldan ulaşan hiçbir şey bundan etkilenmez.

Middleware'i token tazelemek ve açıkça çıkış yapmış ziyaretçileri panelden uzaklaştırmak için kullanıyorum, çünkü bu bir kullanıcı deneyimi iyileştirmesi. Asıl kontrol sorgunun içinde oluyor.

Önbellek, bir kullanıcının sayfasını memnuniyetle başkasına sunar

Beni asıl korkutan hata bu, çünkü sessiz.

Next.js varsayılan olarak agresif önbellekler ve giriş yapmış bir kullanıcı için render edilmiş sayfa, önbellek açısından sadece bir sayfadır. Server Component'te çerez okursanız Next o rotayı statik render'dan çıkarır, ki istediğiniz davranış budur. Kullanıcı verisini çerezlere dokunmayan bir yoldan çekerseniz, hesaplar arasında geçiş yapan önbelleklenmiş bir yanıtla karşılaşabilirsiniz.

Kullanıcıya özel veri render eden her rota bunu çıkarıma bırakmak yerine açıkça belirtmeli. Ve gerçekten test etmeye değer: iki tarayıcıda iki hesapla giriş yapıp aynı rotayı açın. İki dakika sürer ve emin olmanın tek yolu budur.

Bugün başlayan birine söyleyeceğim

Yetkilendirmeyi veritabanına koyun, sunucuda doğrulayın, istemciyi yalnızca görüntü katmanı sayın, ve hangi rotaların kişiye özel olduğunu açıkça belirtin.

Bunların hiçbiri egzotik değil. Auth'a her zaman uygulanan aynı disiplin; sadece framework kodunuzu artık üç yerde çalıştırdığı ve aralarındaki sınırlar düzenlediğiniz dosyada görünmediği için fark edilmesi zorlaşmış durumda.

Bu işin yanlış giden versiyonu genelde yanlış kütüphane ya da eksik özellik değil. Bir katman yukarıda duran bir kontrol.

Sıkça sorulan sorular

Sunucuda getSession mı getUser mı kullanmalıyım?

getUser. getSession çerezi auth sunucusuna doğrulatmadan çözer, yani sunucuda çözülmüş bir token'ı doğrulanmış saymış olursunuz. getUser bir gidiş dönüşe mal olur ve o gidiş dönüş zaten doğrulamanın kendisidir.

Bir rotayı korumak için middleware yeterli mi?

Hayır. Middleware edge'de, veritabanınız olmadan çalışır; belirli bir kullanıcının neye izinli olduğunu soramaz ve oradan yapılan yönlendirme güvenlik sınırı değil rota kararıdır. Onu oturum tazelemek için kullanın, asıl kontrolü sorguya koyun.

Supabase ile yetkilendirme nerede olmalı?

Veritabanında, satır seviyesi güvenlik olarak. Route handler'daki kontrol o rotayı korur. Tablodaki politika, sonradan yazılanlar dahil veriye ulaşan her yolu korur. Test şu: bütün route dosyalarını silseniz veri hâlâ korunur mu?