Claude
Skills
Sign in
Back

authjs-skills

Included with Lifetime
$97 forever

Auth.js v5 setup for Next.js authentication including Google OAuth, credentials provider, environment configuration, and core API integration

Web Dev

What this skill does


## Links

- Getting Started: https://authjs.dev/getting-started/installation?framework=Next.js
- Migrating to v5: https://authjs.dev/getting-started/migrating-to-v5
- Google Provider: https://authjs.dev/getting-started/providers/google
- Credentials Provider: https://authjs.dev/getting-started/providers/credentials
- Core API Reference: https://authjs.dev/reference/core
- Session Management: https://authjs.dev/getting-started/session-management
- Concepts: https://authjs.dev/concepts

## Installation

```sh
pnpm add next-auth@beta
```

**Note**: Auth.js v5 is currently in beta. Use `next-auth@beta` to install the latest v5 version.

## What's New in Auth.js v5?

### Key Changes from v4

- **Simplified Configuration**: More streamlined setup with better TypeScript support
- **Universal `auth()` Export**: Single function for authentication across all contexts
- **Enhanced Security**: Improved CSRF protection and session handling
- **Edge Runtime Support**: Full compatibility with Edge Runtime and middleware
- **Better Type Safety**: Improved TypeScript definitions throughout

## Environment Variables

### Required Environment Variables

```env
# Auth.js Configuration
AUTH_SECRET=your_secret_key_here

# Google OAuth (if using Google provider)
AUTH_GOOGLE_ID=your_google_client_id
AUTH_GOOGLE_SECRET=your_google_client_secret

# For production deployments
AUTH_URL=https://yourdomain.com

# For development (optional, defaults to http://localhost:3000)
# AUTH_URL=http://localhost:3000
```

### Generating AUTH_SECRET

```sh
# Generate a random secret (Unix/Linux/macOS)
openssl rand -base64 32

# Alternative using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

# Using pnpm
pnpm dlx auth secret
```

**Important**: Never commit `AUTH_SECRET` to version control. Use `.env.local` for development.

## Basic Setup (Next.js App Router)

### 1. Create `auth.ts` Configuration File

Create `auth.ts` at the project root (next to `package.json`):

```typescript
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import Credentials from "next-auth/providers/credentials"

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Google({
      clientId: process.env.AUTH_GOOGLE_ID,
      clientSecret: process.env.AUTH_GOOGLE_SECRET,
    }),
    Credentials({
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      authorize: async (credentials) => {
        // TODO: Implement your authentication logic here
        // This is a basic example - see Credentials Provider section below for complete implementation
        if (!credentials?.email || !credentials?.password) {
          return null
        }

        // Example: validate against database (placeholder)
        // See "Credentials Provider" section for full implementation with bcrypt
        const user = { id: "1", email: credentials.email, name: "User" } // Replace with actual DB lookup
        
        if (!user) {
          return null
        }

        return {
          id: user.id,
          email: user.email,
          name: user.name,
        }
      },
    }),
  ],
  pages: {
    signIn: '/auth/signin',
  },
  callbacks: {
    authorized: async ({ auth }) => {
      // Return true if user is authenticated
      return !!auth
    },
  },
})
```

**Note**: This is a basic setup example. For production-ready credentials authentication, see the "Credentials Provider" section below which includes proper password hashing with bcrypt and database integration.

### 2. Create API Route Handler

Create `app/api/auth/[...nextauth]/route.ts`:

```typescript
import { handlers } from "@/auth"

export const { GET, POST } = handlers
```

### 3. Add Middleware (Optional but Recommended)

Create `middleware.ts` at the project root:

```typescript
export { auth as middleware } from "@/auth"

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
```

For more control:

```typescript
import { auth } from "@/auth"

export default auth((req) => {
  const isLoggedIn = !!req.auth
  const isOnDashboard = req.nextUrl.pathname.startsWith('/dashboard')
  
  if (isOnDashboard && !isLoggedIn) {
    return Response.redirect(new URL('/auth/signin', req.url))
  }
})

export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*'],
}
```

## Google OAuth Provider

### 1. Google Cloud Console Setup

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing
3. Enable Google+ API
4. Create OAuth 2.0 credentials:
   - Application type: Web application
   - Authorized redirect URIs:
     - Development: `http://localhost:3000/api/auth/callback/google`
     - Production: `https://yourdomain.com/api/auth/callback/google`
5. Copy Client ID and Client Secret to `.env.local`

### 2. Configuration

```typescript
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Google({
      clientId: process.env.AUTH_GOOGLE_ID,
      clientSecret: process.env.AUTH_GOOGLE_SECRET,
      authorization: {
        params: {
          prompt: "consent",
          access_type: "offline",
          response_type: "code"
        }
      }
    }),
  ],
})
```

### 3. Google Provider Options

```typescript
Google({
  clientId: process.env.AUTH_GOOGLE_ID,
  clientSecret: process.env.AUTH_GOOGLE_SECRET,
  // Request additional scopes
  authorization: {
    params: {
      scope: "openid email profile",
      prompt: "select_account", // Force account selection
    }
  },
  // Allow specific domains only
  allowDangerousEmailAccountLinking: false,
})
```

## Credentials Provider (Username/Password)

### Required Dependencies

```sh
# Install required packages for credentials provider
pnpm add bcryptjs zod
pnpm add -D @types/bcryptjs
```

### 1. Basic Configuration

```typescript
import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
import { z } from "zod"
import bcrypt from "bcryptjs"
import { prisma } from "@/lib/prisma"

const credentialsSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
})

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Credentials({
      credentials: {
        email: { label: "Email", type: "email", placeholder: "[email protected]" },
        password: { label: "Password", type: "password" },
      },
      authorize: async (credentials) => {
        try {
          const { email, password } = credentialsSchema.parse(credentials)
          
          // Fetch user from database
          const user = await prisma.user.findUnique({
            where: { email },
          })

          if (!user) {
            throw new Error("User not found")
          }

          // Verify password
          const isValidPassword = await bcrypt.compare(password, user.hashedPassword)
          
          if (!isValidPassword) {
            throw new Error("Invalid password")
          }

          // Return user object (must include id)
          return {
            id: user.id,
            email: user.email,
            name: user.name,
            image: user.image,
          }
        } catch (error) {
          console.error("Authentication error:", error)
          return null
        }
      },
    }),
  ],
  session: {
    strategy: "jwt", // Required for credentials provider
  },
})
```

### 2. User Registration Example

```typescript
// app/api/auth/register/route.ts
import { NextResponse } from "next/server"
import bcrypt from "bcryptjs"
import { z } from "zod"
import { prisma } from "@/lib/prisma"

const registerSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
  name: z.string().min(2),
})

export async function POST(req: Request) {
  try {
    const 

Related in Web Dev