Web Locks API dapat menghentikan lima tab yang terbuka agar tidak secara bersamaan membanjiri server autentikasi dengan panggilan refresh-token, sehingga menyelamatkan pengguna dari logout mendadak. Dengan mengoordinasikan pembaruan di berbagai tab, satu permintaan menggantikan banjir permintaan yang biasanya memicu penghentian sesi saat Refresh Token Rotation digunakan.
Beban berlebih tersembunyi dalam sesi multi-tab
Aplikasi single-page pada umumnya menambahkan Axios interceptor yang memantau respons 401, mengubah flag Boolean isRefreshing, dan mengantrekan permintaan keluar hingga JWT baru tiba. Jika diuji dalam satu tab, alur ini berjalan tanpa hambatan.
Buka aplikasi yang sama di lima tab, biarkan access token kedaluwarsa, dan kelima tab tersebut akan mendeteksi 401 pada milidetik yang sama. Setiap tab mengira ia harus melakukan refresh, sehingga lima permintaan refresh-token yang identik berebut mengakses server autentikasi. Dengan Refresh Token Rotation—sebuah langkah keamanan yang membatalkan refresh token sebelumnya segera setelah token baru diterbitkan—server akan menganggap permintaan kedua sebagai serangan replay, menandai sesi sebagai telah dikompromikan, dan mencabutnya. Pengguna akan langsung keluar (logout) dari setiap tab dalam sekejap.
Akar masalahnya adalah model isolasi JavaScript. Variabel seperti isRefreshing hanya ada di tab yang mengaturnya; tab lain tidak punya cara untuk mengetahui bahwa proses refresh sedang berlangsung. Hasilnya adalah masalah konkurensi klasik, tetapi "proses" yang terlibat adalah tab browser, bukan thread.
Mengapa lock lintas-tab adalah alat yang tepat
Yang kita butuhkan adalah cara bagi tab untuk saling berkomunikasi mengenai sumber daya bersama—dalam hal ini, JWT yang baru. Web Locks API, yang diekspos sebagai navigator.locks, memberikan hal tersebut secara tepat. API ini memungkinkan skrip meminta lock bernama yang ditegakkan oleh browser di semua konteks yang berasal dari origin yang sama. Jika lock sudah dipegang, pemanggil lain akan masuk antrean hingga pemegang lock melepaskannya atau browser membatalkannya (misalnya, saat tab crash). Tanpa server eksternal, tanpa polling, hanya koordinasi asli browser.
Mengimplementasikan alur refresh berbasis lock
- Deteksi 401 – Axios interceptor menangkap respons tidak sah seperti sebelumnya.
- Minta lock eksklusif – Tab memanggil
navigator.locks.request('auth_token_refresh_lock', async lock => { … }). Hanya satu tab yang dapat masuk ke callback pada satu waktu. - Periksa ulang sebelum mengakses jaringan – Di dalam lock, baca timestamp (atau token itu sendiri) dari
localStorage. Jika timestamp tersebut berusia kurang dari beberapa detik, tab lain sudah memperbarui token; tab saat ini akan melewati panggilan jaringan dan cukup membaca JWT baru dari penyimpanan. - Refresh jika diperlukan – Jika timestamp yang tersimpan sudah usang, kirim permintaan refresh, simpan token baru dan waktu saat ini di
localStorage, lalu lepaskan lock dengan cara keluar dari callback. - Lanjutkan permintaan yang diantrekan – Semua tab lain yang sedang menunggu akan mendapatkan lock satu per satu, melihat timestamp yang baru, dan selesai tanpa melakukan permintaan lain.
async function refreshIfNeeded() {
await navigator.locks.request('auth_token_refresh_lock', async lock => {
const lastRefresh = Number(localStorage.getItem('token_refreshed_at') || 0);
const now = Date.now();
if (now - lastRefresh < 5_000) return; // another tab already refreshed
const newToken = await callRefreshEndpoint(); // actual network call
localStorage.setItem('jwt', newToken);
localStorage.setItem('token_refreshed_at', now.toString());
});
}
Pola ini menjamin bahwa, tidak peduli berapa banyak tab yang terbuka, hanya satu permintaan refresh yang mencapai server.
Manfaat yang dapat Anda ukur
- Efisiensi jaringan – Satu permintaan menggantikan lima permintaan, secara drastis memangkas bandwidth dan beban server.
- Keamanan sesi – Dengan Refresh Token Rotation, server hanya melihat satu kali penggunaan refresh token lama, sehingga tidak akan pernah menandai sesi sebagai telah dikompromikan.
- Resiliensi – Jika tab yang memegang lock mengalami crash, browser secara otomatis melepaskan lock tersebut, mencegah deadlock yang dapat menghentikan semua tab.
- Skalabilitas – Pengguna dapat membuka puluhan tab tanpa risiko logout berantai, karena koordinasi tetap berada di dalam browser.
Sisi lainnya: dukungan browser dan fallback
Web Locks API adalah fitur yang relatif baru. Browser berbasis Chromium modern dan versi terbaru Firefox telah mengimplementasikannya, tetapi browser lama dan Safari belum memiliki dukungan asli. Di lingkungan di mana API ini tidak tersedia, pengembang harus beralih ke teknik yang kurang andal—seperti menyiarkan event kustom melalui localStorage atau menggunakan shared worker—untuk mendekati sinyal lintas-tab. Solusi alternatif tersebut tidak memiliki perlindungan deadlock otomatis yang disediakan oleh navigator.locks, sehingga harus digunakan dengan hati-hati.
Apa yang perlu diperhatikan selanjutnya
- Kemajuan standardisasi – Pantau terus kurva adopsi API; dukungan yang lebih luas akan menjadikan pendekatan berbasis lock sebagai standar default untuk koordinasi lintas-tab apa pun.
- Wrapper pustaka – Beberapa utilitas open-source sudah mulai mengabstraksi pola permintaan lock, sehingga lebih mudah untuk diintegrasikan ke dalam interceptor Axios yang sudah ada.
- Audit keamanan – Meskipun lock tersebut menyelesaikan masalah konkurensi, endpoint refresh tetap harus menerapkan rotasi token dan pembatasan laju (rate limiting) yang tepat, karena satu tab berbahaya masih dapat membanjiri server dengan permintaan jika lock dilewati.
Intinya sederhana: perlakukan sekumpulan tab yang terbuka sebagai sistem terdistribusi dan berikan mereka primitif sinkronisasi asli. Dengan menghubungkan Web Locks API ke dalam alur token-refresh, pengembang dapat menghilangkan "jebakan token tab browser" dan menjaga pengguna tetap masuk, tidak peduli berapa banyak tab yang mereka buka secara bersamaan.
