In this tutorial, we will set up the Next.js 13 App Router along with NextAuth.js for authentication.
Goal
- Prepare the Next.js 13 App directory
- Set up NextAuth.js (or Auth.js)
- Access session data in
server components
,client components
, andAPI routes
Setting up the Next.js Project
Use one of the following commands to create a Next.js app, or skip this step if you already have a project.
pnpm create next-app nextauth-nextjs13-prisma
# or
yarn create next-app nextauth-nextjs13-prisma
# or
npx create-next-app@latest nextauth-nextjs13-prisma
You will be prompted to choose a few options. Here are the recommended choices:
- Would you like to use TypeScript? Yes
- Would you like to use ESLint? Yes
- Would you like to use Tailwind CSS? Yes
- Would you like to use the
src/
directory? Yes - Would you like to use the App Router? (recommended) Yes
- Would you like to customize the default import alias (@/*)? No
Setting up NextAuth API Route
Install Package
Install NextAuth.js using one of the following commands:
pnpm add next-auth
# or
npm i next-auth
# or
yarn add next-auth
Create Config File
Create a /src/lib/auth.ts
file and paste the following code:
import type { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export const authOptions: NextAuthOptions = {
session: {
strategy: "jwt",
},
providers: [
CredentialsProvider({
name: "Sign in",
credentials: {
email: {
label: "Email",
type: "email",
placeholder: "example@example.com",
},
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
const user = { id: "1", name: "Admin", email: "admin@admin.com" };
return user;
},
}),
],
};
Here we use the CredentialsProvider
from NextAuth. You can explore other providers on the official website. For simplicity, this example bypasses database verification, allowing any username and password to sign in.
Create Route File
Create /src/app/api/auth/[...nextauth]/route.ts
and add the following:
import { authOptions } from "@/lib/auth";
import NextAuth from "next-auth";
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
Create Environment File
Create a .env
file in the root of your project. Replace the secret with a secure one for production use:
NEXTAUTH_SECRET=your_super_secure_secret
NEXTAUTH_URL=http://localhost:3000
Create Reusable Buttons (for Demonstration)
Create a /src/components/buttons.tsx
file with the following code:
"use client";
import { signIn, signOut } from "next-auth/react";
import Link from "next/link";
export const LoginButton = () => (
<button onClick={()=> signIn()} className="bg-gray-400/50 px-5 py-3 rounded-2xl">
Sign in
</button>
);
export const RegisterButton = () => (
<Link href="/register" className="bg-gray-400/50 px-5 py-3 rounded-2xl">
Register
</Link>
);
export const LogoutButton = () => (
<button onClick={()=> signOut()} className="bg-gray-400/50 px-5 py-3 rounded-2xl">
Sign Out
</button>
);
export const ProfileButton = () => (
<Link href="/profile" className="bg-gray-400/50 px-5 py-3 rounded-2xl">
Profile
</Link>
);
Display Buttons on the Home Page
Edit /src/app/page.tsx
and replace all content with the following:
import {
LoginButton,
LogoutButton,
ProfileButton,
RegisterButton,
} from "@/components/buttons";
export default async function Home() {
return (
<main className="flex flex-col items-center justify-center min-h-screen py-2 gap-8">
<div className="flex flex-row gap-4">
<LoginButton />
<RegisterButton />
<LogoutButton />
<ProfileButton />
</div>
</main>
);
}
Start the development server and go to http://localhost:3000/
. It should look like this:
- Click
Sign In
to be redirected to the sign-in page. - Enter any username and password to sign in and return to the home page.
To view cookies, check the Application tab in your developer console.
Getting NextAuth Session Data
With the setup complete, let’s look at how to get and use session data.
Getting the Session in a Server Component
You can retrieve session data in a React Server Component by calling getServerSession
with the authOptions
object we created.
Edit /src/app/page.tsx
as follows:
import {
LoginButton,
LogoutButton,
ProfileButton,
RegisterButton,
} from "@/components/buttons";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export default async function Home() {
const session = await getServerSession(authOptions);
return (
<main className="flex flex-col items-center justify-center min-h-screen py-2 gap-8">
<div className="flex flex-row gap-4">
<LoginButton />
<RegisterButton />
<LogoutButton />
<ProfileButton />
</div>
<div className="flex flex-col gap-2">
<h1 className="font-bold">NextAuth.js Server Session data</h1>
<pre>{JSON.stringify(session, null, 2)}</pre>
</div>
</main>
);
}
This code uses const session = await getServerSession(authOptions);
to fetch the server session and display it.
Getting the Session in Route Handlers (API)
Next.js 13 introduced Route Handlers, which operate on the server. Here, we’ll use getServerSession
with authOptions
.
Create /src/app/api/session/route.ts
:
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
const session = await getServerSession(authOptions);
return NextResponse.json({
authenticated: !!session,
session,
});
}
Visit http://localhost:3000/api/session
to see the session data.
Getting the Session in a Client Component
To get session data in a client component (marked with use client
), use the useSession
hook. Note there might be slight latency as the server decodes the JWT token.
First, create a session provider:
Create /src/app/providers.tsx
and add the following:
"use client";
import { SessionProvider } from "next-auth/react";
type Props = {
children?: React.ReactNode;
};
export const Providers = ({ children }: Props) => {
return <SessionProvider>{children}</SessionProvider>;
};
Then wrap your site in this session provider. Modify /src/app/layout.tsx
:
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
import { Providers } from "@/app/providers";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<Providers>{children}</Providers>
</body>
</html>
);
}
Now you can use useSession
inside a client component:
Create /src/components/user.tsx
:
"use client";
import { useSession } from "next-auth/react";
export const User = () => {
const { data: session } = useSession();
return (
<div className="flex flex-col gap-2">
<h1 className="font-bold">NextAuth.js Client Session data</h1>
<pre>{JSON.stringify(session, null, 2)}</pre>
</div>
);
};
Add
an import to /src/app/page.tsx
:
import { User } from "@/components/user";
export default async function Home() {
const session = await getServerSession(authOptions);
return (
<main className="flex flex-col items-center justify-center min-h-screen py-2 gap-8">
<div className="flex flex-row gap-4">
<LoginButton />
<RegisterButton />
<LogoutButton />
<ProfileButton />
</div>
<div className="flex flex-col gap-2">
<h1 className="font-bold">NextAuth.js Server Session data</h1>
<pre>{JSON.stringify(session, null, 2)}</pre>
<User />
</div>
</main>
);
}
Conclusion
And that’s it! You now have a basic setup of NextAuth with Next.js 13. For more advanced features, like integrating a database or using additional providers, subscribe to my newsletter to get updates when I release new tutorials.
Thanks for reading!