Server Side Authentication
In this project, a session based server side authentication using firebase/auth is demonstrated. Visit the github repo or the blog post for details.
You may clone the repo and start your own project ready to handle firebase auth.
> git clone https://github.com/donis3/next-firebase-starter.git
🔸 Route '/' (homepage) Unprotected
This is the homepage. It renders the rootLayout. Suspense is used so server components that needs time to render doesn't block the root layout render.
/* layout.tsx */
<html lang="en">
<body className="min-w-[300px]">
<Suspense fallback={<NavigationLoading />}>
<Navigation />
</Suspense>
<main className="container mx-auto">
<Suspense fallback={<Loading />}>{children}</Suspense>
</main>
<Notifications />
</body>
</html>
🔸 Navbar Component (app/_components/Navigation.tsx)
This is a server component that will call a server action to get current auth user if available. It'll display profile and logout links if authenticated and a login link otherwise.
Because of the backend calls, it may take a while to load. If it's not wrapped with a suspense boundary, it'll block the whole root layout and the user will stare at a blank screen. Thats why we provide a suspense and a fallback component that looks like the same navbar but without the auth links.
This is how we fetch the currently authenticated user in a server component. Note that we use getAuthAction() instead of directly importing getCurrentUser from lib/firebase-auth-api.ts.
If the backend code is not called via a server action in a component, revalidatePath may not remove the cache and we might get a stale version of the component. For example, we logout but navbar still shows a profile button like we are still logged in. Fetching data using a server action makes sure the component is revalidated when revalidatePath('/') is called
/* Navigation.tsx > */
export default async function Navigation() {
const user = (await getAuthAction()) as UserRecord | undefined;
// ...render component according to user state
// ...
}