# Implementing Authentication in Next.js with NextAuth.js

NextAuth.js is a popular authentication library for Next.js that simplifies the process of implementing user authentication. It provides a robust and customizable solution for handling different authentication methods, including credentials, OAuth providers, and more. This guide walks you through setting up a basic authentication system in a Next.js application using NextAuth.js.

---

## Step 1: Install NextAuth.js

First, install NextAuth.js and the necessary dependencies:

```bash
npm install next-auth @next-auth/prisma-adapter
```

If you plan to use a database, make sure you have an ORM like Prisma or an appropriate adapter installed.

---

## Step 2: Create an API Route for Authentication

NextAuth.js requires an API route to handle authentication requests. Create a new file `src/pages/api/auth/[...nextauth].ts`:

```typescript
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';

export default NextAuth({
  providers: [
    Providers.GitHub({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    }),
    // Add more providers as needed
  ],
  callbacks: {
    async session({ session, user }) {
      session.user.id = user.id;
      return session;
    },
  },
  secret: process.env.NEXTAUTH_SECRET,
});
```

This configuration uses GitHub as an OAuth provider. Replace `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` with your GitHub app credentials. You can add other providers as needed.

---

## Step 3: Configure Environment Variables

Add the required environment variables in a `.env.local` file at the root of your project:

```typescript
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_secret_key
```

Replace `your_github_client_id`, `your_github_client_secret`, and `your_secret_key` with appropriate values.

---

## Step 4: Protect Pages Using Middleware

Instead of using `getServerSession`, we can use middleware to protect routes and handle redirections. Create a middleware file in `src/middleware.ts`:

```typescript
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';

export async function middleware(req) {
  const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
  const { pathname } = req.nextUrl;

  // Allow access to public paths
  if (pathname.startsWith('/api/auth') || pathname === '/signin') {
    return NextResponse.next();
  }

  // Redirect if no token is found
  if (!token) {
    return NextResponse.redirect(new URL('/signin', req.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: [
    '/protected/:path*', // Protect paths that start with /protected
  ],
};
```

This middleware checks for a valid session token and redirects unauthenticated users to the sign-in page.

---

## Step 5: Add the Sign-In and Sign-Out Components

To allow users to sign in and out, create a simple component using NextAuth.js hooks:

```typescript
import { useSession, signIn, signOut } from 'next-auth/react';

export default function AuthButton() {
  const { data: session } = useSession();

  if (session) {
    return (
      <>
        <p>Signed in as {session.user.email}</p>
        <button onClick={() => signOut()}>Sign Out</button>
      </>
    );
  }

  return <button onClick={() => signIn()}>Sign In</button>;
}
```

---

## Step 6: Customize the Authentication Flow (Optional)

You can customize the authentication flow by modifying the `pages` property in the NextAuth.js configuration:

```typescript
export default NextAuth({
  pages: {
    signIn: '/auth/signin',
    signOut: '/auth/signout',
    error: '/auth/error',
    verifyRequest: '/auth/verify-request',
    newUser: '/auth/new-user',
  },
});
```

Create the corresponding pages in the `src/pages/auth` directory to match the paths defined above.

---

## Benefits of Using Middleware for Authentication

1. **Centralized Logic:** Middleware handles authentication at the route level, simplifying server-side logic.
    
2. **Performance:** Only restricted pages trigger session validation.
    
3. **Flexibility:** Easily configure protected and public routes.
    

---

## Additional Resources for NextAuth.js

To dive deeper into NextAuth.js and related topics, explore the following resources:

1. [NextAuth.js Documentation](https://next-auth.js.org/getting-started/example) - Official documentation with detailed guides and examples.
    
2. [Securing Next.js Applications](https://nextjs.org/learn/dashboard-app/adding-authentication) - Learn more about authentication strategies in Next.js.
    

These links provide additional insights and examples to help you expand your knowledge and make the most of NextAuth.js in your projects.
