0% found this document useful (0 votes)
23 views9 pages

Pages Router

This document provides a comprehensive guide on setting up server-side authentication in Next.js using Supabase, covering both App Router and Pages Router strategies. It includes steps for installing necessary packages, configuring environment variables, creating utility functions for different Supabase clients, and implementing login and authentication confirmation features. Additionally, it explains how to protect pages for authenticated users and fetch static data using Supabase in Next.js applications.

Uploaded by

Felipe Montero
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views9 pages

Pages Router

This document provides a comprehensive guide on setting up server-side authentication in Next.js using Supabase, covering both App Router and Pages Router strategies. It includes steps for installing necessary packages, configuring environment variables, creating utility functions for different Supabase clients, and implementing login and authentication confirmation features. Additionally, it explains how to protect pages for authenticated users and fetch static data using Supabase in Next.js applications.

Uploaded by

Felipe Montero
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

DOCS Search

Auth

Auth Server-Side Rendering Next.js guide

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.

App Router Pages Router Hybrid router strategies

1 Install Supabase packages

Install the @supabase/supabase-js package and the helper @supabase/ssr package.

1 npm install @supabase/supabase-js @supabase/ssr

2 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

eCow / eCow Ranch Management

https://ioauubebagztwzpefnjm.supabase.co

Anon key

eCow / eCow Ranch Management


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im

.env.local
1 NEXT_PUBLIC_SUPABASE_URL=<your_supabase_project_url>
2 NEXT_PUBLIC_SUPABASE_ANON_KEY=<your_supabase_anon_key>

3 Write utility functions to create Supabase clients

To access Supabase from your Next.js app, you need 4 types of Supabase clients:

1 getServerSideProps client - To access Supabase from getServerSideProps .

2 getStaticProps client - To access Supabase from getStaticProps .

3 Component client - To access Supabase from within components.


4 API route client - To access Supabase from API route handlers.

Create a utils/supabase folder with a file for each type of client. Then copy the utility
functions for each client type.

Why do I need so many types of clients?

What does the `cookies` object do?


utils/supabase/server-props.ts utils/supabase/static-… utils/supabase/comp… utils/supabase/…
1 import { type GetServerSidePropsContext } from 'next'
2 import { createServerClient, serializeCookieHeader } from '@supabase/ssr'
3
4 export function createClient({ req, res }: GetServerSidePropsContext) {
5 const supabase = createServerClient(
6 process.env.NEXT_PUBLIC_SUPABASE_URL!,
7 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
8 {
9 cookies: {
10 getAll() {
11 return Object.keys(req.cookies).map((name) => ({ name, value: req.coo
12 },
13 setAll(cookiesToSet) {
14 res.setHeader(
15 'Set-Cookie',
16 cookiesToSet.map(({ name, value, options }) =>
17 serializeCookieHeader(name, value, options)
18 )
19 )
20 },
21 },
22 }
23 )
24
25 return supabase
26 }

4 Create a login page

Create a login page for your app.

Since Supabase is being called from a component, use the client defined in
@/utils/supabase/component.ts .
pages/login.tsx
1 import { useRouter } from 'next/router'
2 import { useState } from 'react'
3
4 import { createClient } from '@/utils/supabase/component'
5
6 export default function LoginPage() {
7 const router = useRouter()
8 const supabase = createClient()
9
10 const [email, setEmail] = useState('')
11 const [password, setPassword] = useState('')
12
13 async function logIn() {
14 const { error } = await supabase.auth.signInWithPassword({ email, password
15 if (error) {
16 console.error(error)
17 }
18 router.push('/')
19 }
20
21 async function signUp() {
22 const { error } = await supabase.auth.signUp({ email, password })
23 if (error) {
24 console.error(error)
25 }
26 router.push('/')
27 }
28
29 return (
30 <main>
31 <form>
32 <label htmlFor="email">Email:</label>
33 <input id="email" type="email" value={email} onChange={(e) => setEmail(
34 <label htmlFor="password">Password:</label>
35 <input
36 id="password"
37 type="password"
38 value={password}
39 onChange={(e) => setPassword(e.target.value)}
40 />
41 <button type="button" onClick={logIn}>
42 Log in
43 </button>
44 <button type="button" onClick={signUp}>
45 Sign up
46 </button>
47 </form>
48 </main>
49 )
50 }

5 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 the Confirm signup template,
change {{ .ConfirmationURL }} to {{ .SiteURL }}/api/auth/confirm?token_hash=
{{ .TokenHash }}&type=signup .

6 Create a route handler for Auth confirmation

Create an API route for api/auth/confirm . When a user clicks their confirmation email
link, exchange their secure code for an Auth token.

Since this is an API route, use the Supabase client from @/utils/supabase/api.ts .
pages/api/auth/confirm.ts pages/error.tsx
1 import { type EmailOtpType } from '@supabase/supabase-js'
2 import type { NextApiRequest, NextApiResponse } from 'next'
3
4 import createClient from '@/utils/supabase/api'
5
6 function stringOrFirstString(item: string | string[] | undefined) {
7 return Array.isArray(item) ? item[0] : item
8 }
9
10 export default async function handler(req: NextApiRequest, res: NextApiResponse
11 if (req.method !== 'GET') {
12 res.status(405).appendHeader('Allow', 'GET').end()
13 return
14 }
15
16 const queryParams = req.query
17 const token_hash = stringOrFirstString(queryParams.token_hash)
18 const type = stringOrFirstString(queryParams.type)
19
20 let next = '/error'
21
22 if (token_hash && type) {
23 const supabase = createClient(req, res)
24 const { error } = await supabase.auth.verifyOtp({
25 type: type as EmailOtpType,
26 token_hash,
27 })
28 if (error) {
29 console.error(error)
30 } else {
31 next = stringOrFirstString(queryParams.next) || '/'
32 }
33 }
34
35 res.redirect(next)
36 }

7 Make an authenticated-only page using `getServerSideProps`

If you use dynamic server-side rendering, you can serve a page to authenticated users only
by checking for the user data in getServerSideProps . Unauthenticated users will be
redirected to the home page.
Since you're calling Supabase from getServerSideProps , use the client from
@/utils/supabase/server-props.ts .

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. 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.

pages/private.tsx
1 import type { User } from '@supabase/supabase-js'
2 import type { GetServerSidePropsContext } from 'next'
3
4 import { createClient } from '@/utils/supabase/server-props'
5
6 export default function PrivatePage({ user }: { user: User }) {
7 return <h1>Hello, {user.email || 'user'}!</h1>
8 }
9
10 export async function getServerSideProps(context: GetServerSidePropsContext) {
11 const supabase = createClient(context)
12
13 const { data, error } = await supabase.auth.getUser()
14
15 if (error || !data) {
16 return {
17 redirect: {
18 destination: '/',
19 permanent: false,
20 },
21 }
22 }
23
24 return {
25 props: {
26 user: data.user,
27 },
28 }
29 }
8 Fetch static data using `getStaticProps`

You can also fetch static data at build time using Supabase. Note that there's no session or
user at build time, so the data will be the same for everyone who sees the page.

Add some countries data to your database by running the Countries Quickstart in the
dashboard.

Then fetch the countries data using getStaticProps with the client from
@/utils/supabase/static-props.ts .

pages/public.tsx
1 import { createClient } from '@/utils/supabase/static-props'
2
3 export default function PublicPage({ data }: { data?: any[] }) {
4 return <pre>{data && JSON.stringify(data, null, 2)}</pre>
5 }
6
7 export async function getStaticProps() {
8 const supabase = createClient()
9
10 const { data, error } = await supabase.from('countries').select()
11
12 if (error || !data) {
13 return { props: {} }
14 }
15
16 return { props: { data } }
17 }

Congratulations

You're done! To recap, you've successfully:


Called Supabase from a component

Called Supabase from an API route

Called Supabase from getServerSideProps

Called Supabase from getStaticProps

You can now use any Supabase features from your client or server code!

Edit this page on GitHub

Need some help? Contact support

Latest product updates? See Changelog


Something's not right? Check system status

© Supabase Inc

Contributing

Author Styleguide

Open Source

SupaSquad

Privacy Settings

You might also like