Setting up Server-Side Auth for Next.js
Next.js comes in two flavors: the App Router and the Pages Router. You can set up Server-Side Auth with either strategy. You can even use both in the same application.
Install Supabase packages
Install the @supabase/supabase-js
package and the helper @supabase/ssr
package.
_10npm install @supabase/supabase-js @supabase/ssr
Set up environment variables
Create a .env.local
file in your project root directory.
Fill in your NEXT_PUBLIC_SUPABASE_URL
and NEXT_PUBLIC_SUPABASE_ANON_KEY
:
Project URL
Anon key
Write utility functions to create Supabase clients
To access Supabase from your Next.js app, you need 3 types of Supabase clients:
- Client Component client - To access Supabase from Client Components, which run in the browser.
- Server Component client - To access Supabase from Server Components, which run only on the server.
- Server Action client - To access Supabase from Server Actions and Route Handlers.
Create a utils/supabase
folder with a file for each type of client. Then copy the utility functions for each client type.
Hook up middleware
Create a middleware.ts
file at the root of your project.
Since Server Components can't write cookies, you need middleware to refresh expired Auth tokens and store them. Copy the code to refresh the Auth token whenever it's expired.
Add a matcher so the middleware doesn't run on routes that don't access Supabase.
Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone.
Always use supabase.auth.getUser()
to protect pages and user data.
Never trust supabase.auth.getSession()
inside server code such as middleware. It isn't guaranteed to revalidate the Auth token.
It's safe to trust getUser()
because it sends a request to the Supabase Auth server every time to revalidate the Auth token.
Create a login page
Create a login page for your app. Use a Server Action to call the Supabase signup function.
Since Supabase is being called from an Action, use the client defined in @/utils/supabase/actions.ts
.
Change the Auth confirmation path
If you have email confirmation turned on (the default), a new user will receive an email confirmation after signing up.
Change the email template to support a server-side authentication flow.
Go to the Auth templates page in your dashboard. In each email template, change {{ .ConfirmationURL }}
to {{ .SiteURL }}/auth/callback?token_hash={{ .TokenHash }}&type=signup
.
Create a route handler for Auth confirmation
Create a Route Handler for auth/callback
. When a user clicks their confirmation email link, exchange their secure code for an Auth token.
Since this is a Router Handler, use the Supabase client from @/utils/supabase/actions.ts
.
Access user info from Server Component
Server Components can read cookies, so you can get the Auth status and user info.
Since you're calling Supabase from a Server Component, use the client created in @/utils/supabase/server.ts
.
Create a private
page that users can only access if they're logged in. The page displays their email.
Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone.
Always use supabase.auth.getUser()
to protect pages and user data.
Never trust supabase.auth.getSession()
inside Server Components. It isn't guaranteed to revalidate the Auth token.
It's safe to trust getUser()
because it sends a request to the Supabase Auth server every time to revalidate the Auth token.
Congratulations
You're done! To recap, you've successfully:
- Called Supabase from a Server Action
- Called Supabase from a Server Component
- Set up a Supabase client utility to call Supabase from a Client Component
- Set up middleware to automatically refresh the Supabase Auth session
You can now use any Supabase features from your client or server code!