Login loop karena cookie session tidak persist adalah salah satu bug paling membingungkan saat memakai Supabase Auth dengan SSR, middleware, atau backend yang membaca sesi dari cookie. Gejalanya khas: proses sign-in terlihat sukses, redirect berjalan, tetapi setelah refresh atau navigasi berikutnya user dianggap logout dan dikirim kembali ke halaman login.
Dalam banyak kasus, masalahnya bukan pada kredensial user atau query ke database, melainkan pada session cookie yang tidak pernah benar-benar tersimpan, tidak ikut terkirim pada request berikutnya, atau dibaca tidak konsisten antara browser, middleware, dan server. Artikel ini membahas studi kasus debugging yang fokus pada akar masalah tersebut dan cara memperbaikinya dengan aman.
Gejala yang Terlihat di Browser, Middleware, dan Backend
Gejala di browser
Dari sisi pengguna, alurnya sering terlihat seperti ini:
- User mengisi email dan password.
- Response login sukses, kadang UI sempat menampilkan state authenticated.
- Aplikasi melakukan redirect ke halaman protected seperti
/dashboard. - Begitu halaman direfresh, atau saat user membuka route lain, aplikasi kembali ke
/login.
Jika diperiksa di DevTools, sering terlihat salah satu kondisi berikut:
- Response login mengandung
Set-Cookie, tetapi cookie tidak muncul di browser storage. - Cookie muncul, tetapi tidak ikut terkirim pada request ke route protected.
- Cookie hanya tersedia untuk path tertentu, bukan seluruh aplikasi.
- Cookie diset untuk domain yang berbeda dari domain aplikasi yang sedang diakses.
Gejala di middleware
Pada aplikasi yang memakai middleware untuk proteksi route, gejalanya biasanya lebih spesifik:
- Middleware selalu menganggap user anonim meskipun login baru saja sukses.
- Redirect bolak-balik antara
/logindan/dashboard. - Log middleware menunjukkan cookie kosong atau token tidak dapat di-refresh.
Masalah ini sering muncul ketika middleware membaca session dari cookie, tetapi cookie itu sendiri tidak terset dengan benar atau tidak diteruskan pada request berikutnya.
Gejala di backend atau SSR
Pada sisi server, Anda mungkin melihat pola seperti:
- Endpoint login mengembalikan sukses.
- Endpoint SSR/API berikutnya tidak menemukan session user.
- Server kadang membaca user sebagai login, kadang tidak, tergantung jalur request.
Ketidakkonsistenan ini biasanya menandakan ada perbedaan cara membaca session antara browser-side dan server-side, atau atribut cookie membuat cookie hanya berlaku pada kondisi tertentu saja.
Studi Kasus: Kronologi Investigasi
Langkah awal yang tampak meyakinkan, tetapi menyesatkan
Kasus umum dimulai seperti ini:
- Tim melihat login berhasil karena response dari Supabase Auth sukses.
- UI client menampilkan bahwa session tersedia segera setelah sign-in.
- Karena itu, fokus investigasi diarahkan ke middleware atau logic redirect.
Ini hipotesis yang masuk akal, tetapi sering salah. Session yang tersedia sesaat di memori client tidak otomatis berarti browser berhasil mempersist cookie untuk request selanjutnya.
Hipotesis yang sempat dicurigai tetapi ternyata bukan akar masalah
- Query profil user lambat atau gagal — ternyata bukan, karena redirect ke login terjadi sebelum data profil dipakai.
- Middleware salah memproteksi route — terkadang middleware memang ketat, tetapi masalah utamanya adalah ia tidak menerima cookie session yang valid.
- Supabase sedang gagal refresh token — bisa terjadi, tetapi sering kali refresh tidak mungkin berjalan karena cookie dasarnya tidak pernah ikut terkirim.
- Cache browser atau race condition UI — kadang berperan, tetapi bukan penyebab utama login loop yang konsisten.
Titik balik investigasi
Titik balik biasanya terjadi saat memeriksa dua hal secara berdampingan:
- Header
Set-Cookiepada response login. - Header
Cookiepada request berikutnya ke halaman SSR, middleware, atau API protected.
Jika response login sudah mengirim Set-Cookie tetapi request berikutnya tidak membawa Cookie yang relevan, maka masalahnya hampir pasti ada pada persistensi atau cakupan cookie.
Root Cause yang Paling Sering Menyebabkan Login Loop
1. Cookie tidak pernah benar-benar terset
Ini skenario paling dasar. Response login tampak sukses, tetapi browser menolak cookie. Penyebab umum:
- Atribut
Securedipakai di environment non-HTTPS. - Atribut
SameSite=Nonedipakai tanpaSecure, sehingga ditolak browser modern. - Domain cookie tidak cocok dengan host saat ini.
- Path terlalu sempit, misalnya hanya berlaku untuk
/auth. - Response yang seharusnya membawa cookie terpotong atau tertimpa oleh response/redirect lain.
2. Domain cookie salah
Kesalahan domain sering terjadi saat local, staging, dan production memakai hostname berbeda. Contohnya:
- Aplikasi dibuka di
app.example.com, tetapi cookie diset untukapi.example.com. - Di lokal, aplikasi dibuka lewat
127.0.0.1tetapi cookie diasumsikan untuklocalhost.
Browser menganggap itu domain berbeda. Akibatnya, cookie tidak tersedia di request yang Anda kira membutuhkannya.
3. Path cookie terlalu sempit
Jika cookie diset dengan path seperti /auth, maka route seperti /dashboard atau middleware global tidak akan menerima cookie tersebut. Untuk session aplikasi, path yang aman umumnya adalah / agar seluruh route dapat membacanya.
4. SameSite tidak sesuai pola request
SameSite menentukan kapan cookie boleh dikirim dalam konteks navigasi lintas origin atau lintas situs. Jika arsitektur Anda melibatkan domain berbeda untuk app dan auth flow, nilai SameSite yang terlalu ketat dapat membuat cookie tidak pernah ikut pada alur tertentu.
Trade-off-nya:
- Lax lebih aman untuk banyak kasus aplikasi web biasa.
- None diperlukan pada beberapa skenario cross-site, tetapi harus disertai
Secure.
Jangan memilih nilai ini hanya agar bug hilang; pastikan sesuai dengan topologi domain aplikasi Anda.
5. Secure aktif di HTTP lokal
Di production, Secure sangat disarankan karena cookie hanya dikirim lewat HTTPS. Namun di local development yang masih HTTP biasa, cookie dengan Secure tidak akan bekerja. Hasilnya tampak seperti login berhasil, padahal session tidak pernah persist.
6. Pembacaan session di server tidak konsisten
Masalah tidak selalu pada penulisan cookie. Kadang cookie ada, tetapi server membacanya dari request yang salah atau pada tahap yang tidak konsisten. Contoh pola bug:
- Client membaca session dari memori internal, sementara SSR mengandalkan cookie request.
- Middleware memeriksa request sebelum cookie hasil refresh diteruskan.
- API route menggunakan helper/adapter yang tidak membaca header cookie dari request saat ini.
Akibatnya, client merasa login tetapi server menolak akses karena sumber kebenaran session berbeda.
Cara Mereproduksi Bug secara Terkontrol
Sebelum memperbaiki, buat reproduksi yang jelas agar Anda bisa membuktikan akar masalah. Gunakan langkah seperti ini:
- Buka aplikasi dalam mode incognito agar bebas dari cookie lama.
- Masuk melalui form login biasa.
- Perhatikan apakah redirect ke route protected berhasil.
- Refresh halaman protected.
- Pindah ke route protected lain.
- Buka DevTools dan periksa cookie yang tersimpan untuk origin aplikasi.
- Bandingkan request sebelum login, sesudah login, dan sesudah refresh.
Jika bug konsisten muncul pada refresh pertama setelah login, sangat mungkin session hanya hidup di state client, bukan di cookie yang benar-benar dipakai server.
Langkah Debugging yang Efektif
1. Periksa header Set-Cookie pada response login
Di tab Network browser, buka request login atau callback auth yang relevan, lalu lihat response headers. Anda perlu memastikan ada Set-Cookie yang benar-benar dikirim.
Contoh bentuk yang perlu Anda evaluasi:
Set-Cookie: sb-session=...; Path=/; HttpOnly; SameSite=Lax
Set-Cookie: sb-refresh=...; Path=/; HttpOnly; SameSite=LaxYang harus dicek:
- Apakah header itu benar-benar ada?
- Apakah nama cookie sesuai yang diharapkan oleh layer server Anda?
- Apakah ada
Domain,Path,Secure, danSameSiteyang masuk akal? - Apakah response login diikuti redirect yang justru menimpa atau menghilangkan cookie?
Jika
Set-Cookietidak ada sama sekali, fokuskan investigasi pada jalur backend yang membuat response login. Jika ada tetapi cookie tetap tidak muncul di browser storage, fokuskan investigasi pada atribut cookie.
2. Periksa apakah browser benar-benar menyimpan cookie
Setelah response login diterima, buka panel Application/Storage di browser dan lihat cookie untuk origin aplikasi. Cocokkan atributnya:
- Domain
- Path
- Expires/Max-Age
- HttpOnly
- Secure
- SameSite
Jika cookie tidak muncul, browser kemungkinan menolaknya. Banyak browser menampilkan alasan penolakan di DevTools, misalnya karena Secure atau kombinasi SameSite yang tidak valid.
3. Periksa header Cookie pada request berikutnya
Ini langkah paling penting. Ambil request ke route protected, middleware target, atau API yang seharusnya hanya bisa diakses user login. Lihat request headers dan pastikan browser mengirim:
Cookie: sb-session=...; sb-refresh=...Jika cookie tersimpan tetapi tidak ikut terkirim, hampir pasti masalahnya ada pada:
- Domain tidak cocok.
- Path tidak mencakup endpoint yang diminta.
- Secure/HTTP mismatch.
- SameSite memblokir pengiriman cookie dalam konteks request itu.
4. Tambahkan logging aman di middleware dan API route
Jangan log token mentah ke production log. Namun untuk debugging lokal atau staging, Anda bisa log keberadaan cookie dan sebagian metadata.
// Contoh generik di middleware / API route
const cookieHeader = request.headers.get('cookie') || ''
console.log('has session cookie:', cookieHeader.includes('sb-session='))
console.log('has refresh cookie:', cookieHeader.includes('sb-refresh='))Tujuannya bukan membaca isi token, tetapi memastikan request yang masuk memang membawa cookie yang Anda harapkan.
5. Verifikasi pembacaan session di SSR/API route
Jika Anda menggunakan server-side rendering atau route handler, pastikan pembacaan session selalu berasal dari request saat ini, bukan dari state client. Contoh pemeriksaan generik:
// Pseudocode generik
export async function handleRequest(request) {
const cookieHeader = request.headers.get('cookie')
// buat auth client / adapter menggunakan cookie dari request saat ini
// lalu baca user/session dari sumber itu
}Kesalahan umum adalah membuat auth client global yang tidak terikat pada request sekarang, sehingga sesi user menjadi acak atau stale.
6. Uji redirect flow
Pada beberapa implementasi, login dilakukan di satu endpoint lalu diteruskan ke route lain. Pastikan response yang mengandung Set-Cookie benar-benar sampai ke browser. Jika ada beberapa lapis proxy, load balancer, atau redirect internal, cek apakah header cookie dipertahankan.
Contoh Pemeriksaan yang Praktis
Menggunakan browser DevTools
- Buka tab Network.
- Lakukan login.
- Pilih request login/callback.
- Lihat Response Headers dan cari
Set-Cookie. - Buka request berikutnya ke halaman protected.
- Lihat Request Headers dan cari
Cookie.
Jika langkah 4 ada tetapi langkah 6 kosong, akar masalah hampir selalu pada konfigurasi cookie.
Menggunakan curl untuk memisahkan browser dari server
Untuk memastikan backend memang mengirim cookie, Anda bisa menguji endpoint terkait dengan curl. Contoh generik:
curl -i https://app.example.com/auth/callbackUntuk mensimulasikan penyimpanan cookie antar request:
curl -i -c cookies.txt -b cookies.txt https://app.example.com/protectedNama endpoint tentu menyesuaikan aplikasi Anda. Tujuannya adalah melihat apakah server mengirim cookie dan apakah cookie itu bisa dipakai lagi pada request berikutnya.
Perbaikan yang Aman
1. Samakan strategi domain aplikasi dan auth
Jika memungkinkan, hindari arsitektur yang membuat session cookie harus bekerja lintas domain yang tidak perlu. Menyatukan app dan route auth di origin yang sama biasanya paling sederhana dan paling stabil.
Jika memang harus memakai subdomain berbeda, pastikan Anda sengaja mengatur domain cookie sesuai kebutuhan dan memahami dampaknya pada keamanan serta pengiriman cookie.
2. Gunakan path cookie yang mencakup seluruh aplikasi
Untuk session login, Path=/ biasanya pilihan yang benar. Ini memastikan middleware, SSR, API route, dan halaman biasa bisa menerima cookie yang sama.
3. Sesuaikan Secure dengan environment
- Local HTTP: jangan memaksa cookie session dengan
Securejika Anda belum memakai HTTPS lokal. - Staging/Production HTTPS: aktifkan
Secure.
Perbedaan ini sering menjadi penyebab bug yang hanya muncul di lokal atau justru hanya muncul setelah deploy.
4. Pilih SameSite berdasarkan topologi request
Jika aplikasi berjalan dalam origin yang sama dan login flow tidak lintas situs, SameSite=Lax sering menjadi default yang aman. Jika ada kebutuhan cross-site yang valid, gunakan None bersama Secure. Jangan longgarkan kebijakan tanpa alasan yang jelas.
5. Pastikan pembacaan session server selalu berbasis request saat ini
Pada SSR dan API route, auth client atau helper untuk membaca session sebaiknya dibuat per request. Dengan begitu, cookie yang dibaca selalu sesuai dengan user dan request yang sedang diproses.
6. Hindari sumber kebenaran ganda
Jangan mengandalkan state client sebagai indikator akhir bahwa user sudah login jika route protected Anda sebenarnya dikontrol server/middleware. Dalam arsitektur berbasis SSR, cookie request adalah sumber kebenaran utama untuk otorisasi awal.
Contoh Checklist Validasi Setelah Perbaikan
- Login sukses.
- Response login mengandung
Set-Cookie. - Cookie terlihat di browser storage.
- Cookie terkirim pada refresh halaman protected.
- Middleware membaca user dengan konsisten.
- API route protected menerima cookie yang sama.
- Logout menghapus cookie yang relevan.
- Flow bekerja sama baik di local, staging, dan production.
Kesalahan Umum yang Perlu Dihindari
- Menganggap login sukses hanya karena response auth sukses.
- Tidak membedakan session di memori client dengan session yang dipersist ke cookie.
- Memeriksa hanya browser storage tanpa memeriksa request header berikutnya.
- Menyetel atribut cookie yang aman untuk production, tetapi dipakai mentah-mentah di local HTTP.
- Menggunakan host campuran seperti
localhostdan127.0.0.1dalam satu flow. - Membuat auth helper global di server yang tidak terikat ke request aktif.
Checklist Pencegahan untuk Local, Staging, dan Production
Local development
- Gunakan satu hostname secara konsisten, jangan campur
localhostdan127.0.0.1. - Jika masih HTTP, pastikan konfigurasi cookie tidak mewajibkan
Secure. - Periksa DevTools setiap kali mengubah flow login atau middleware.
- Uji refresh halaman protected, bukan hanya redirect sesaat setelah login.
Staging
- Samakan perilaku domain dan HTTPS semirip mungkin dengan production.
- Tambahkan logging aman untuk mendeteksi apakah cookie masuk ke middleware dan API route.
- Uji dari browser bersih agar tidak tertutup cookie lama.
- Pastikan proxy atau gateway tidak membuang header cookie.
Production
- Gunakan HTTPS penuh dan aktifkan
Secureuntuk session cookie. - Tinjau
SameSitesesuai kebutuhan arsitektur, jangan terlalu longgar tanpa alasan. - Pastikan domain cookie sesuai dengan domain aplikasi yang benar-benar mengonsumsi session.
- Monitor pola redirect abnormal yang bisa menandakan login loop.
- Hindari logging isi token; log hanya keberadaan cookie dan jalur request bila perlu.
Penutup
Bug login loop karena cookie session tidak persist pada Supabase Auth hampir selalu bisa diurai jika Anda memeriksa alur request-response secara disiplin: apakah Set-Cookie dikirim, apakah browser menyimpannya, apakah Cookie ikut pada request berikutnya, dan apakah server membacanya dari request yang benar.
Jika sesi tampak berhasil dibuat tetapi user terus kembali ke halaman login setelah refresh atau navigasi, jangan langsung menyalahkan middleware atau query backend. Mulailah dari fakta paling dasar: apakah cookie session benar-benar ada dan benar-benar dipakai. Dari situ, akar masalah biasanya cepat terlihat.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!