Implementing Authentication in Next.js 14 with Auth.js: A Step-by-Step Guide
Authentication is a critical component of many web applications. In this guide, we'll walk through the process of implementing a robust authentication system in a Next.js 14 project using Auth.js, a powerful and flexible authentication library.
By Vasili Zalimidis —
With the release of Next.js 14, integrating authentication into your application has become more streamlined, especially with the power of Auth.js (formerly NextAuth.js). This guide will walk you through setting up authentication using TypeScript, leveraging the latest features and best practices.
1. Setting Up the Project
First, ensure you have a Next.js 14 project initialized. If you haven't started one yet, you can create a new project:
npx create-next-app@latest my-next-app
cd my-next-app
Then, install the next-auth package:
npm install next-auth@beta
The @beta tag is essential here, as it ensures you are using the latest features of Auth.js compatible with Next.js 14.
2. Configuring Auth.js
Auth.js requires a configuration file where you'll define your authentication providers, session management, and callbacks. Create a file named auth.ts at the root of your project:
// auth.ts
import NextAuth from "next-auth";
import GitHubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
secret: process.env.AUTH_SECRET!,
});
3. Setting Up API Routes
In Next.js 14, you'll place your API routes within the app directory, particularly under app/api/auth/[...nextauth]/route.ts:
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
4. Using Authentication in Your Components
With the configuration set up, you can now integrate authentication into your React components. For server-side rendering or API routes, use the auth() function:
import { auth } from "@/auth";
export default async function ServerComponent() {
const session = await auth();
return (
<div>
{session?.user ? (
<p>Welcome, {session.user.name}!</p>
) : (
<p>Please sign in.</p>
)}
</div>
);
}
For client-side components, the useSession() hook remains the go-to approach:
"use client";
import { useSession, signIn, signOut } from "next-auth/react";
const ClientComponent = () => {
const { data: session } = useSession();
return (
<div>
{session ? (
<>
<p>Welcome, {session.user?.name}</p>
<button onClick={() => signOut()}>Sign out</button>
</>
) : (
<button onClick={() => signIn()}>Sign in</button>
)}
</div>
);
};
export default ClientComponent;
5. Environment Variables
Ensure you have the necessary environment variables in your .env.local file:
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
AUTH_SECRET=your-auth-secret
The AUTH_SECRET is critical for token encryption and should be generated using a secure method, such as the npx auth secret command.
6. Advanced Configuration
Auth.js also supports lazy initialization, which can be useful for dynamic provider configurations or request-specific settings:
import NextAuth from "next-auth";
import GitHubProvider from "next-auth/providers/github";
export const { handlers, auth } = NextAuth((req) => {
return {
providers: [
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
],
};
});
Conclusion
Integrating authentication in a Next.js 14 application using Auth.js is straightforward and powerful. With the combination of TypeScript and modern Next.js features, you can build secure and scalable applications quickly.