If you have encountered problems setting up authentication with Next.js 14 and Supabase on the client side, this is probably the article you need to read.
To summarize: we want to use auth on Next.js 14 on the client side with Supabase. The new package @supabase/auth-helpers-nextjs offers us new methods to implement our authentication system.
However, after consulting Supabase Auth with the Next.js App Router written by Jon Meyers, I still couldn't implement the client-side solution. For some reason, middleware wouldn't catch my session.
I don't know if I was getting things mixed up, but after hours of research, after reading Andrew Smith's comment on Stackoverflow I managed to find the solution.
Here's how to proceed:
1/ Only use @supabase/auth-helpers-nextjs & not @supabase/supabase-js
2/ Create a client to export with @supabase/auth-helpers-nextjs
// @lib/supabase.ts
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs";
export const supabase = createClientComponentClient()
3/ Use it everywhere (login example)
// login.ts
...
const login = async () => {
const { email, password } = data;
try {
setLoading(true);
const { data, error } = await supabase
.auth
.signInWithPassword({
email,
password
})
if (error) return setError('Sorry impossible to login.');
if (data) {
const { user } = data
const { access_token, refresh_token } = data.session
await supabase.auth.setSession({
access_token,
refresh_token
})
setUser(user)
router.refresh() // very important! we'll catch session on middleware
}
} catch (error: any) {
throw new Error(error)
} finally {
setLoading(false);
}
}
...
4/ Setup a middleware:
// middleware.ts
import { createMiddlewareClient } from "@supabase/auth-helpers-nextjs";
import { NextRequest, NextResponse } from "next/server";
export async function middleware(req: NextRequest) {
const res = NextResponse.next()
const supabase = createMiddlewareClient({ req, res })
const {
data: {
session
}
} = await supabase.auth.getSession()
if (!session) {
return NextResponse.rewrite(new URL('/login', req.url))
}
return res
}
export const config = {
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico).*)',
]
}
5/ You're good to go.
Guillaume Duhan
Top comments (0)