Skip to content

Supabase Auth session bugSupabase logs users out when they refresh the page

A user signs in, refreshes the page and is back on the login screen. Or they stay signed in for about an hour, then every request fails. Supabase keeps sessions going by default, so something in how the app stores or refreshes the session is cutting it short. Here’s where to look, in Supabase’s own words, or hand it over at a fixed price.

Short answer

In a Next.js or other server-rendered app, use the @supabase/ssr clients so the session lives in cookies, and add the middleware (proxy.ts on Next.js 16) that refreshes it on every request. In a browser-only app, create one Supabase client with persistSession on, and wait for the stored session to load before your route guard sends anyone to the login page.

Why the session disappears, most common cause first

  1. 01

    Next.js has no middleware refreshing the session

    “Since Next.js Server Components can't write cookies, you need a Proxy to refresh expired Auth tokens and store them.” Supabase, Creating a Supabase client for SSR

    Server Components can read the auth cookie but can’t write a refreshed one, so a Next.js app needs the middleware from Supabase’s guide. Name the file for your version: proxy.ts with a proxy function on Next.js 16, middleware.ts with a middleware function before that. A proxy.ts on Next.js 15 is ignored, and users are signed out once the access token expires. Also check the matcher doesn’t skip the pages users land on.

  2. 02

    The session is in local storage, but the server checks cookies

    “You need to make a few changes to the configuration of your Supabase client, to store the user session in cookies instead of local storage.” Supabase, Server-Side Rendering

    The plain supabase-js client saves the session in the browser’s local storage, which the server never sees. A server-rendered page then finds no session and redirects to login on every refresh, even though the browser is signed in. Switch to createBrowserClient and createServerClient from @supabase/ssr, which store the session in cookies.

    import { createBrowserClient } from '@supabase/ssr';
    
    export const supabase = createBrowserClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL!,
      process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
    );
  3. 03

    The route guard runs before the session loads

    On a fresh page load the client reads the stored session asynchronously. A guard that checks for a user on the first render sees none and redirects to login, which looks like a lost session. Show a loading state until onAuthStateChange fires its INITIAL_SESSION event, then decide. Create the client once in a shared module: a second client with persistSession set to false, or configured with a different storage key, won’t see the saved session.

  4. 04

    Nothing refreshes the access token

    “Access tokens are designed to be short lived, usually between 5 minutes and 1 hour while refresh tokens never expire but can only be used once.” Supabase, User sessions

    Access tokens are short lived and the refresh token renews them. If autoRefreshToken is off, or the app calls the API with a token it saved itself, requests start failing when that token expires. In React Native, pass AsyncStorage as the client’s storage and start and stop auto refresh with the app’s foreground state, as Supabase’s quickstart shows.

  5. 05

    A session setting ends sessions early

    “Sessions are not proactively destroyed when you change these settings, but rather the check is enforced whenever a session is refreshed next.” Supabase, User sessions

    On Pro plans and up, the Auth settings Time-box user sessions, Inactivity timeout and Single session per user all end sessions on purpose. If one is on, users are signed out at the next refresh after the limit, which can feel random. Turn it off or raise it if that isn’t what you want.

Checked against the vendor’s docs on : Supabase docs: Creating a Supabase client for SSR (Next.js); Supabase docs: Server-Side Rendering; Supabase docs: User sessions; Supabase reference: getSession; Supabase reference: onAuthStateChange; Supabase docs: React Native quickstart.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Supabase auth emails link to localhost · Google sign-in redirect_uri_mismatch · Supabase RLS fixes · Supabase public storage bucket

Questions

More on this error

Users are logged out after about an hour. Is that a session limit?

Usually not. By default a Supabase session lasts until the user signs out; the access token is what expires, often after an hour. When users drop out on that schedule, the token isn’t being refreshed: check the Next.js middleware, autoRefreshToken, and whether the app reuses a token it stored itself.

Can I check getSession() in my middleware to protect pages?

Supabase’s Next.js guide says not to: getSession() reads the session from the cookie without checking it, and anyone can forge a cookie. Use getClaims() in server code, which verifies the token’s signature.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; we reply by email, usually within one business day.