Next.js Authentication: Secure Your App with NextAuth.js
Simplify User Authentication in Next.js Apps Using NextAuth.js
Authentication is a critical part of any web application, ensuring that only authorized users can access certain areas and functionalities. In this tutorial, we'll explore how to implement secure authentication in a Next.js application using NextAuth.js, a flexible and easy-to-use authentication library for Next.js.
Setting Up Your Next.js Project
Before we dive into authentication, let's setup a basic Next.js project. If you haven't already, install the Next.js CLI and create a new project:
npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm install
Installing NextAuth.js
Next, install NextAuth.js and its required dependencies:
npm install next-auth
Configuring NextAuth.js
Create a new file called next-auth.js
in the pages/api/auth
directory. This file will configure NextAuth.js for your application:
// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';
export default NextAuth({
providers: [
Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
// Add more providers here
],
// Optional: Customize pages
pages: {
signIn: '/auth/signin',
signOut: '/auth/signout',
error: '/auth/error',
verifyRequest: '/auth/verify-request',
newUser: '/auth/new-user',
},
// Optional: Custom callbacks
callbacks: {
async signIn(user, account, profile) {
return true;
},
async redirect(url, baseUrl) {
return baseUrl;
},
async session(session, user) {
session.userId = user.id;
return session;
},
async jwt(token, user, account, profile, isNewUser) {
return token;
},
},
});
Environment Variables
NextAuth.js requires environment variables for the authentication providers. Create a .env.local
file in the root of your project and add the following:
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
Make sure to replace your-google-client-id
and your-google-client-secret
with your actual Google OAuth credentials. You can obtain these from the Google Developer Console.
Creating Authentication Pages
NextAuth.js provides default authentication pages, but you can customize them by creating your own. Create the following files in the pages/auth
directory:
signin.js
signout.js
error.js
verify-request.js
new-user.js
Here's an example of a custom sign-in page:
// pages/auth/signin.js
import { providers, signIn, getSession, csrfToken } from 'next-auth/client';
export default function SignIn({ providers, csrfToken }) {
return (
<div>
<h1>Sign In</h1>
{Object.values(providers).map((provider) => (
<div key={provider.name}>
<button onClick={() => signIn(provider.id)}>
Sign in with {provider.name}
</button>
</div>
))}
</div>
);
}
export async function getServerSideProps(context) {
const { req } = context;
const session = await getSession({ req });
const providers = await providers();
const csrfToken = await csrfToken(context);
if (session) {
return { redirect: { destination: '/' } };
}
return {
props: { providers, csrfToken },
};
}
Protecting Pages
To protect certain pages or routes, you can use the useSession
hook provided by NextAuth.js. Here’s an example of how to protect a page:
// pages/protected.js
import { useSession, signIn } from 'next-auth/client';
export default function ProtectedPage() {
const [session, loading] = useSession();
if (loading) return <div>Loading...</div>;
if (!session) {
return (
<div>
<h1>You are not signed in</h1>
<button onClick={() => signIn()}>Sign in</button>
</div>
);
}
return (
<div>
<h1>Welcome, {session.user.name}</h1>
</div>
);
}