After a user signs up or signs in, we redirect that user to the home page. In turn, the src/app/page.js route code is executed on the server.
src/app/page.js
export default function HomePage() { console.log("I'm running on the server!") return <div>Hello World </div>}
Our goal is to send the ID token from the client to the server so that we can access it within this route. Then we can dynamically render the home page.
How do we send the ID Token to the server? There are a couple ways we can do this..
Upon sign up or sign in, we can put the ID token into a cookie. (Remember, cookies are sent to the server on every request, automatically.)
When the user signs up / signs in, we'll grab their idToken and stick it in a cookie. Then it'll be sent to the server automatically on subsequent requests.
Here's how you can set the cookie after the user signs up / signs in. Note that this code runs on the client.
"use client"// (imports and other code not shown) ...createUserWithEmailAndPassword(auth, email, password) .then(async (userCredential) => { const user = userCredential.user // Get the idToken from the user object return user.getIdToken().then((idToken) => { // Build the cookie string let cookie = `idToken=${idToken}; SameSite=Lax;` if (window.location.hostname !== "localhost") cookie += " secure;" // Set the cookie document.cookie = cookie // Redirect to the home page // refresh() to prevent Next.js caching router.push("/") router.refresh() }) }) .catch((error) => { console.log("Error:", error) })// (jsx and other code not shown) ...
"use client"// (imports and other code not shown) ...signInWithEmailAndPassword(auth, email, password) .then(async (userCredential) => { const user = userCredential.user // Get the idToken from the user object return user.getIdToken().then((idToken) => { // Build the cookie string let cookie = `idToken=${idToken}; SameSite=Lax;` if (window.location.hostname !== "localhost") cookie += " secure;" // Set the cookie document.cookie = cookie // Redirect to the home page // refresh() to prevent Next.js caching router.push("/") router.refresh() }) }) .catch((error) => { console.log("Error:", error) })// (jsx and other code not shown) ...
Now, when a user signs up or signs in, you should see this cookie appear in the cookies section of the Application in Chrome DevTools.
You should also see this cookie being delivered to the server when you inspect Network requests.
With Next.js, you can get access to the cookie server-side with cookies().get() 👇
src/app/page.js
import { cookies } from "next/headers"import { Home } from "./Home"export default async function HomePage() { const idToken = cookies().get("idToken") console.log("idToken", idToken) return <div>Hello World </div>}
In particular, FIREBASE_AUTH_EMULATOR_HOST tells the verifyIdToken() method to relax the rules for checking the ID token while the Emulator is running.
Rather than rely on the short-lived token issued by Firebase, why don't we just exchange it for our own long-lived token? That's exactly the solution proposed here.
Rather than copy the linked article, I'll just outline the steps.
Create an API endpoint ("route handler" in Next.js) that recives the short-lived token and exchanges is for a long-lived token. The key to this step is to use the createSessionCookie() method.
Tweak the Sign up and Sign in methods such that they make make a request to that API endpoint with the ID Token. If successful, the API should return a response with the Set-Cookie with the new token.
On subsequent requests to the server, use the verifySessionCookie() method to verify the session cookie.
The service worker method is described in detail here. I'm too burned out to add details to this approach, but if you're struggling to understand it, reach out to me.