Web Locks API, beş açık sekmenin aynı anda bir auth sunucusuna refresh-token çağrıları yaparak yüklenmesini engelleyebilir ve kullanıcıları ani oturum kapatmalardan kurtarabilir. Sekmeler arası yenileme işlemlerini koordine ederek, Refresh Token Rotation kullanıldığında normalde oturumun sonlandırılmasına neden olan yoğun istek dalgasının yerine tek bir istek gönderilmesini sağlar.

Çoklu sekme oturumlarındaki gizli aşırı yük

Tipik bir tek sayfa uygulaması (SPA), 401 yanıtını izleyen, bir Boolean isRefreshing bayrağını değiştiren ve yeni bir JWT gelene kadar giden tüm istekleri sıraya koyan bir Axios interceptor'ı ekler. Tek bir sekmede test edildiğinde, akış kusursuz çalışır.

Aynı uygulamayı beş sekmede açın, erişim token'ının (access token) süresinin dolmasına izin verin; beş sekmenin tamamı aynı milisaniyede 401 hatasını fark edecektir. Her sekme yenileme yapması gerektiğini düşünür, bu nedenle beş özdeş refresh-token isteği auth sunucusuna hücum eder. Yeni bir token düzenlendiği anda önceki refresh token'ı geçersiz kılan bir güvenlik önlemi olan Refresh Token Rotation ile sunucu, ikinci isteği bir replay attack (tekrar saldırısı) olarak görür, oturumu tehlikede olarak işaretler ve iptal eder. Kullanıcı, bir anda tüm sekmelerden çıkış yapmış olur.

Temel neden JavaScript'in izolasyon modelidir. isRefreshing gibi bir değişken yalnızca onu ayarlayan sekmede yaşar; diğer sekmelerin bir yenileme işleminin halihazırda devam ettiğini bilmesinin bir yolu yoktur. Sonuç, klasik bir eşzamanlılık (concurrency) problemidir, ancak buradaki "süreçler" thread'ler değil, tarayıcı sekmeleridir.

Neden sekmeler arası bir kilit (lock) doğru araçtır

İhtiyacımız olan şey, sekmelerin paylaşılan bir kaynak —bu durumda taze JWT— hakkında birbirleriyle konuşabilmelerini sağlayacak bir yoldur. navigator.locks olarak sunulan Web Locks API, tam olarak bunu sağlar. Betiklerin, tarayıcının aynı kökene (origin) ait tüm bağlamlarda uyguladığı isimlendirilmiş bir kilit talep etmesine olanak tanır. Eğer bir kilit zaten tutuluyorsa, sahibi kilidi serbest bırakana veya tarayıcı işlemi iptal edene kadar (örneğin sekme çöktüğünde) diğer çağrıcılar sıraya alınır. Harici bir sunucu yok, polling yok, sadece yerel tarayıcı koordinasyonu var.

Kilit tabanlı yenileme akışının uygulanması

  1. 401'i Tespit Edin – Axios interceptor'ı, daha önce olduğu gibi yetkisiz yanıtı yakalar.
  2. Özel bir kilit talep edin – Sekme, navigator.locks.request('auth_token_refresh_lock', async lock => { … }) komutunu çağırır. Aynı anda yalnızca bir sekme callback fonksiyonuna girebilir.
  3. Ağa bağlanmadan önce tekrar kontrol edin – Kilidin içinde, localStorage üzerinden bir zaman damgası (veya token'ın kendisini) okuyun. Eğer zaman damgası birkaç saniyeden daha yeniyse, başka bir sekme token'ı zaten yenilemiştir; mevcut sekme ağ çağrısını atlar ve yeni JWT'yi doğrudan depolamadan okur.
  4. Gerekirse yenileyin – Eğer saklanan zaman damgası eskiyse, yenileme isteğini gönderin, yeni token'ı ve mevcut zamanı localStorage içine kaydedin ve ardından callback'ten dönerek kilidi serbest bırakın.
  5. Sıradaki istekleri devam ettirin – Bekleyen diğer tüm sekmeler kilidi birbiri ardına alır, güncel zaman damgasını görür ve başka bir istek yapmadan işlemi tamamlar.
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());
  });
}

Bu desen, kaç sekme açık olursa olsun, sunucuya yalnızca bir yenileme isteğinin ulaşacağını garanti eder.

Ölçebileceğiniz faydalar

  • Ağ verimliliği – Bir istek beş isteğin yerini alarak bant genişliğini ve sunucu yükünü önemli ölçüde azaltır.
  • Oturum güvenliği – Refresh Token Rotation ile sunucu eski refresh token'ın yalnızca bir kez kullanıldığını görür, böylece oturumu asla tehlikede olarak işaretlemez.
  • Dayanıklılık – Kilidi tutan sekme çökerse, tarayıcı kilidi otomatik olarak serbest bırakır ve aksi takdirde tüm sekmeleri durduracak olan bir kilitlenmeyi (deadlock) önler.
  • Ölçeklenebilirlik – Koordinasyon tarayıcı içinde kaldığı için kullanıcılar, zincirleme bir oturum kapatma riski olmadan düzinelerce sekme açabilirler.

Madalyonun öteki yüzü: tarayıcı desteği ve alternatif yöntemler

Web Locks API nispeten yeni bir özelliktir. Modern Chromium tabanlı tarayıcılar ve Firefox'un güncel sürümleri bunu desteklerken, eski tarayıcılar ve Safari yerel desteğe sahip değildir. API'nin mevcut olmadığı ortamlarda geliştiriciler, sekmeler arası sinyalleşmeyi taklit etmek için localStorage üzerinden özel bir etkinlik yayınlamak veya bir shared worker kullanmak gibi daha az güvenilir tekniklere başvurmalıdır. Bu geçici çözümler, navigator.locks tarafından sağlanan otomatik kilitlenme (deadlock) korumasına sahip olmadığından dikkatli kullanılmalıdır.

Sırada ne var?

  • Standardlaşma süreci – API'nin benimsenme eğrisini takip edin; daha geniş destek, kilit tabanlı yaklaşımı sekmeler arası tüm koordinasyonlar için varsayılan hale getirecektir.
  • Kütüphane sarmalayıcıları – Birkaç açık kaynaklı yardımcı araç, kilit istek desenini halihazırda soyutlaştırarak mevcut Axios interceptor'larına entegre edilmesini kolaylaştırıyor.
  • Güvenlik denetimleri – Kilit, eşzamanlılık sorununu çözse de, yenileme uç noktası (refresh endpoint) yine de uygun token rotasyonu ve hız sınırlamasını (rate limiting) uygulamalıdır; çünkü kilit atlanırsa, tek bir kötü niyetli sekme sunucuyu hala istek yağmuruna tutabilir.

Çıkarılması gereken ders basit: Açık sekmeler kümesini dağıtık bir sistem olarak ele alın ve onlara yerel bir senkronizasyon primitifi sağlayın. Web Locks API'yi token yenileme akışına bağlayarak geliştiriciler, "tarayıcı sekmesi token tuzağını" ortadan kaldırır ve kullanıcılar kaç sekme ile uğraşırsa uğraşsın oturumlarını açık tutarlar.