[▲ Vercel Community](/) · [Categories](/categories) · [Latest](/latest) · [Top](/top) · [Live](/live)

[Help](/c/help/9)

# Preventing flash of unauthenticated content in Next.js SSR with JWT authorization

37 views · 1 like · 3 posts


pablonotescobar (@pablonotescobar) · 2026-02-11

## Introduction

I am creating an SSR app. While implementing JWT authorization, I noticed the flashing of secure content (FOUC) that should not be shown to an unauthorized person. I wrote the backend on `NestJS`, and I have an API route for a refresh token where I `GET` the refresh token, check it, and then, if it is valid, I extend it and return the extended one to the frontend. It’s a basic refresh operation. On the client, in the `useEffect` of the `AuthProvider`, I make the request with the refresh token. I also have a state called `loaded` to watch for the response. `AuthProvider` is in my main layout.

## Issue

Because my app uses SSR, the server renders the HTML and returns it faster than the client-side JavaScript starts working. Consequently, I see secure content for a few seconds before the `router.replace` redirect to the `/sign-in` path occurs. I have tried several solutions:

1.  **Server Component Auth:** I tried making the auth component a server component, but I couldn't pass the refresh token (stored in cookies) from the server component back to the client component effectively, which broke the JWT flow.
2.  **Validation Route:** I tried a server component that calls a separate API route to just check the token (without extending it). This has two problems: users would have to sign in frequently (depending on refresh token lifetime), and making two requests (one server-side to check, one client-side to extend) is bad for optimization.

I am looking for a way to prevent this flash while maintaining the token refresh logic.

```tsx
'use client' 

import { useEffect, useState } from "react";
import { AuthApi } from "@/features/auth";
import { useRouter } from "next/navigation";
import { useUserStore } from "@/entities/user/model/user-store";

export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
    const [loaded, setLoaded] = useState(false);
    const router = useRouter()
    const setUser = useUserStore(state => state.setUser)
    const user = useUserStore(state => state.id)


    useEffect(() => {
        const initAuth = async () => {
            try {
                const data = await AuthApi.refreshProxy();
                setUser(data.user)

                if (data.user.role !== 'admin') {
                    router.replace('/');
                    return;
                }

            } catch (e) {
                setUser(null)
                router.replace('/sign-in');
            } finally {
                setLoaded(true);
            }
        };

        initAuth();
    }, []);

    if (loaded)
        return children


    return <div>Loading...</div>;
};
```


pablonotescobar (@pablonotescobar) · 2026-02-12 · ♥ 1

Ohhhh nooo, the problem is solved by adding styles to my loading div… 😭😭 I just didnt see this block, so I saw the HTML page… Every AI lied to me, that javascript doesn’t render on Server, so funny, fell very dumb


Amy Egan (@amyegan) · 2026-02-12

I'm glad you found a solution. Thanks for coming back to share what worked for you!