NextAuth with Supabase Adapter
Integrating NextAuth with Supabase Adapter in Next.js
If you're working on Next.js application and looking for a way to implement authentication, combining NextAuth with Supabase's Adapter offers a powerful and streamlined approach. This guide walks you through setting up NextAuth with Supabase to handle authentication in your Next.js application, additionally I'm going to show you how you can protect your routes!
Before we start, make sure you have:
- A Next.js project set up.
- A Supabase account and project created.
Done? Let's get started!
Step 1: Install dependencies
First, we need to add NextAuth and the Supabase Adapter to our project. Run the following command in your project directory
pnpm add next-auth @auth/supabase-adapter
Step 2: Configure NextAuth
Create a route.ts file inside the app/api/auth[...nextauth] directory. This file will configure NextAuth and specify Supabase as the provider. In this tutorial we're gonna use Github Provider, you can use whatever provider you want.
import { SupabaseAdapter } from "@auth/supabase-adapter";
import type { NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import jwt from "jsonwebtoken";
export const authOptions: NextAuthOptions = {
adapter: SupabaseAdapter({
url: process.env.SUPABASE_URL as string,
secret: process.env.SUPABASE_SERVICE as string,
}),
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID as string,
clientSecret: process.env.GITHUB_SECRET as string,
}),
],
callbacks: {
async session({ session, user }) {
const signingSecret = process.env.SUPABASE_JWT_SECRET;
if (signingSecret) {
const payload = {
aud: "authenticated",
exp: Math.floor(new Date(session.expires).getTime() / 1000),
sub: user.id,
email: user.email,
};
session.user.id = user.id;
session.supabaseAccessToken = jwt.sign(payload, signingSecret);
}
return session;
},
},
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
Step 3: Setting Up Environment Variables
You can find these details in your Supabase project settings under the API section:
SUPABASE_URL=
SUPABASE_SERVICE=
SUPABASE_JWT_SECRET=
GITHUB_ID=
GITHUB_SECRET=
Step 4: Using NextAuth for Authentication
With NextAuth and Supabase configured, you can now use NextAuth functions such as signIn, signOut, and useSession to manage user authentication in your application.
import { signIn, signOut, useSession } from "next-auth/react"
const Header = () => {
const { data: session } = useSession()
return (
<header>
{!session ? (
<button onClick={() => signIn("github")}>Sign In</button>
) : (
<button onClick={() => signOut()}>Sign Out</button>
)}
</header>
)
}
Protecting Routes
To ensure that certain pages of your app are accessible only to logged-in users, you can protect your routes by checking the session status.
Client Side
"use client";
import { useSession } from "next-auth/react";
import { redirect } from "next/navigation";
export default function ProtectedClientPage() {
const { data: session } = useSession({
required: true,
onUnauthenticated() {
redirect("/signin");
},
});
return (
<section className="mt-20">
<h1>Hello {session?.user.name}</h1>
</section>
);
};
Server Side
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
export default async function ProtectedServerPage() {
const session = await getServerSession(authOptions);
if (!session) {
redirect("/signin");
}
return (
<section className="mt-20">
<h1>Hello {session?.user.name}</h1>
</section>
);
};
Conclusion
Integrating NextAuth with Supabase in Next.js not only streamlines user authentication but also simplifies protecting your routes. This setup offers a robust yet user-friendly way to manage access to your app, ensuring both a smooth experience and enhanced security for your users.