Fix: Supabase JWT Expired or Invalid Token Error
Quick Answer
Use Supabase's onAuthStateChange listener to automatically refresh tokens. Add this to your app's root layout to handle session persistence across page loads.
Quick Fix Summary
| Issue | JWT token expired |
| Fastest fix | Add auth state listener |
| Use this page if | Error: JWT expired |
Symptoms
- !Error: JWT expired
- !User gets logged out randomly
- !API calls fail with 401 after some time
- !Auth state lost on page refresh
Step-by-Step Fix
Add auth state listener
In your root layout or auth provider, add: supabase.auth.onAuthStateChange((event, session) => { if (event === 'TOKEN_REFRESHED') { /* token auto-refreshed */ } if (event === 'SIGNED_OUT') { router.push('/login') } })
Use getSession not getUser for initial load
On page load, call supabase.auth.getSession() which returns the cached session. getUser() makes a network request and can fail if the token is expired.
Set proper cookie options
If using SSR, configure Supabase Auth with proper cookie settings: createServerClient with cookies options that read/write from Next.js cookies.
Check token expiry settings
In Supabase Dashboard > Authentication > Settings, verify JWT expiry time. Default is 3600 seconds (1 hour). Increase to 86400 (24 hours) for less frequent refresh.
Frequently Asked Questions
Default is 1 hour (3600 seconds). You can change this in Supabase Dashboard > Authentication > Settings. Supabase auto-refreshes tokens if onAuthStateChange is set up.
If you're not persisting the session, the token is lost on refresh. Use Supabase's built-in session persistence with createBrowserClient (for client) or createServerClient (for SSR).
Related
Weekly Signals
Get the next fix, switch, or warning before it hits your build.
Join builders getting the community signals, fix patterns, and tool shifts that matter before they show up everywhere else.
Follow the signals →