Skip to content

TOKEN_REFRESHED loop on init with ECC P-256 signing key - SIGNED_OUT after 30 rapid refreshes #2126

@AndyOgRD

Description

@AndyOgRD

Describe the bug

On every page load, onAuthStateChange receives 30+ TOKEN_REFRESHED events in rapid succession (~100ms apart), followed by a SIGNED_OUT event that kills the session. This happens with zero Realtime channels active, with a clean localStorage, and regardless of supabase-js version (tested on 2.46.0 and 2.94.1).

Library affected

supabase-js

Reproduction

No response

Steps to reproduce

1.Have a Supabase project with ECC (P-256) as the active JWT signing key (migrated automatically by Supabase)
2.Create a React app with a standard AuthProvider using onAuthStateChange
3.Load the app with a valid session in localStorage
4.Observe console logs

1 INITIAL_SESSION event, then normal session behavior with TOKEN_REFRESHED firing at most once per hour.
Actual behavior
INITIAL_SESSION ← normal
TOKEN_REFRESHED ← fires BEFORE INITIAL_SESSION on some reloads
TOKEN_REFRESHED
SIGNED_OUT ← 5-6 seconds after INITIAL_SESSION
SIGNED_IN ← session re-established
TOKEN_REFRESHED ← rapid loop starts
TOKEN_REFRESHED ← ~100ms between each
TOKEN_REFRESHED ← 30+ times
...
SIGNED_OUT ← session killed by "refresh token already used"
Key observations

The loop starts before INITIAL_SESSION is processed — it originates inside the Supabase client initialization, not in application code
The loop occurs with zero Realtime channels active
The loop occurs with clean localStorage (all sb-* keys manually deleted)
A minimal test component with only 2 Realtime channels and no AuthProvider logic works perfectly — no TOKEN_REFRESHED loop
The project recently had its JWT signing key automatically migrated from Legacy HS256 to ECC (P-256) by Supabase
Supabase dashboard settings: Refresh token reuse interval: 30s, Detect and revoke compromised tokens: enabled
The SIGNED_OUT is caused by "refresh token already used" — multiple parallel refresh attempts consuming the same token within the reuse interval

System Info

@supabase/supabase-js: tested on 2.46.0 and 2.94.1 — same behavior on both
@supabase/auth-js: 2.94.1
@supabase/realtime-js: 2.94.1
Browser: Chrome (Windows)
JWT Signing Key: ECC (P-256) (migrated automatically, Legacy HS256 still present as "Previously used key")
React 18, Vite

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinghas workaroundIssue has a valid workaround.needs more infoNeeds more information from the OP. If no info is provided, it will be marked as stale and closed.supabase-jsRelated to the supabase-js library.

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions