Web Applications

Handling Auth Redirects in Next.js Without the Flicker

You’ve all seen it: a protected page loads, shows its content for a split second, then snaps to the login screen. That flash of private content before the redirect is a bad look, and on some apps, a real leak. In Next.js, it happens because the auth redirect decision is made too late, in the browser, after the page already rendered.

Illustration of a web application dashboard, Handling Auth Redirects in Next.js Without the Flicker
Next.js auth redirects that flash private content come from deciding too late, in the browser.

Why the flicker happens

The page renders, a useEffect runs, it sees no session, and only then redirects. By that point the protected UI has already painted. Moving the check earlier removes the flash entirely.

It is worse than it looks. The protected HTML and its data were already sent to the browser, so anyone who views the source or watches the Network tab can read them. A client-side redirect hides the page from honest visitors. It protects nothing from curious ones.

It is also slow. The visitor downloads a page, runs its scripts, and only then starts loading the login screen. That is a full extra round trip, the same kind of wasted work that drags down a store full of add-ons, as I describe in why your Shopify store is slow.

Decide on the server

In Next.js, check the session on the server, in middleware or a Server Component, and redirect there. The browser never receives the protected HTML for an unauthenticated user, so there’s nothing to flash. Middleware is ideal for whole sections of the app: it runs before the page, checks the session cookie, and redirects unauthorized requests before render.

In Next.js 16, the middleware file convention was renamed to proxy, so the file is now proxy.ts. It does the same job. Because it runs on every matched request, including prefetches, keep it light: read the session cookie and redirect, and leave database lookups for later.

For finer control, check the session inside a Server Component and redirect from there. Either way, the decision happens on the server, not after a client round trip.

Infographic summarising “Handling Auth Redirects in Next.js Without the Flicker”: Why the flicker happens; Decide on the server; Setting up Next.js auth redirects step by step; When you still need something in the browser
The article at a glance.

Setting up Next.js auth redirects step by step

The Next.js authentication guide recommends a split between quick checks and secure checks. This is the setup I use:

  1. Store the session in a secure, HTTP-only cookie, so scripts in the page cannot read or change it.
  2. In the proxy, do a quick check. If there is no valid session cookie on a protected path, redirect to the login page before anything renders.
  3. Exclude the login page and static files from the matcher, or you will build a redirect loop.
  4. Verify the session again close to the data. A small function that checks the session and returns the user, called wherever protected data is read, is the real line of defense.
  5. Redirect from Server Components with redirect() from next/navigation when a page needs a role or permission check.
  6. Send people back where they were going. Pass the original path to the login page, and accept only paths on your own site, so the redirect cannot be abused to send users elsewhere.

How to test that it works

  • Open a protected URL in a private window. In the Network tab, the first response should be a redirect, not the page HTML.
  • Turn JavaScript off and try again. You should still land on the login page, because the decision no longer depends on the browser.
  • Log out in one tab, then click around in another. The next navigation should send you to login without showing stale private content.
  • Call your protected data routes directly without a session. They should refuse, whatever the page does.

Common mistakes

  • Relying on the proxy alone. It is a fast first filter. Data reads and server actions still need their own check.
  • Checking only in a layout. Layouts do not re-render on every navigation, so a check there can be skipped. Check in the page or the data layer too.
  • Calling an auth service on every request. A remote session lookup on each page view slows things down and can add to your bill. Reducing API costs in Next.js applications covers how to cache what is safe to cache.
  • Chaining redirects. Each hop adds a full round trip before the real page can start loading.

That last one matters for speed scores. Every redirect pushes back the moment the main content can appear, which is one reason a page can be stuck on a slow Largest Contentful Paint. I break down the rest in the real reason your LCP won’t drop below 2.5s.

When you still need something in the browser

If you must do anything client-side, render a neutral loading state, never the real content, until auth resolves. But the clean answer is to stop the protected page from rendering for the wrong user in the first place.

Client checks still have a place: hiding a menu item, or reacting when a session expires while the page is open. Treat them as convenience for the interface, never as protection. If you are building an app with logins and want this done properly from the start, that is part of my web application development work.

Questions people ask

Why does my protected page flash before redirecting to login?

Because the redirect happens in the browser. The page renders first, then a client-side effect checks the session and redirects. By then the protected content has already painted. Checking the session on the server, in the proxy or a Server Component, means an unauthenticated visitor never receives the page at all.

Should I use middleware or proxy for authentication in Next.js?

In Next.js 16, the middleware file was renamed to proxy, and it fills the same role. Use it for quick, optimistic checks that read the session cookie and redirect. Do not rely on it alone: verify the session again wherever protected data is read, because that check is the real security boundary.

How do I redirect from a Server Component in Next.js?

Import redirect from next/navigation and call it after checking the session, for example when no valid user is found. It stops rendering and sends the visitor to the new path, so the protected markup is never sent. Use it for page-level and role-based checks that need more than a cookie.

Is a client-side auth check secure?

No. By the time a client-side check runs, the browser has usually received the page and often its data, which anyone can read in developer tools. Client checks are fine for interface details like hiding a button, but access control has to happen on the server.

Comments

Leave a comment

0 / 3000
Comments are moderated. Links are not clickable and your email is never published. See the privacy policy.
keep reading

Related articles

Usually replies within a day
let’s talk

Tell me what you want to build

A website, an app, some automation, or something you’re still figuring out. Tell me the problem and I’ll give you a straight answer on what it takes. No pressure, no sales team.