AU

auth-patterns

Provides patterns and code structures for implementing authentication in Next.js applications.

Install

mkdir -p .claude/skills/auth-patterns && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/1902" && unzip -o skill.zip -d .claude/skills/auth-patterns && rm skill.zip

Installs to .claude/skills/auth-patterns

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

This skill should be used when the user asks about "authentication in Next.js", "NextAuth", "Auth.js", "middleware auth", "protected routes", "session management", "JWT", "login flow", or needs guidance on implementing authentication and authorization in Next.js applications.
276 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Configure NextAuth.js providers and callbacks
  • Implement middleware-based route protection
  • Manage session data in server and client components
  • Extend session types for role-based access control
  • Implement JWT and database session strategies

How it works

The skill utilizes NextAuth.js handlers to manage authentication flows, session storage strategies, and middleware protection for specific application routes.

Inputs & outputs

You give it
User credentials or provider tokens
You get back
Authenticated session object and secure cookies

When to use auth-patterns

  • Implement NextAuth
  • Secure API routes
  • Configure JWT authentication

About this skill

Authentication Patterns in Next.js

Overview

Next.js supports multiple authentication strategies. This skill covers common patterns including NextAuth.js (Auth.js), middleware-based protection, and session management.

Authentication Libraries

LibraryBest For
NextAuth.js (Auth.js)Full-featured auth with providers
ClerkManaged auth service
LuciaLightweight, flexible auth
Supabase AuthSupabase ecosystem
Custom JWTFull control

NextAuth.js v5 Setup

Installation

npm install next-auth@beta

Configuration

// auth.ts
import NextAuth from 'next-auth'
import GitHub from 'next-auth/providers/github'
import Credentials from 'next-auth/providers/credentials'

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    Credentials({
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      authorize: async (credentials) => {
        const user = await getUserByEmail(credentials.email)
        if (!user || !verifyPassword(credentials.password, user.password)) {
          return null
        }
        return user
      },
    }),
  ],
  callbacks: {
    authorized: async ({ auth }) => {
      return !!auth
    },
  },
})

API Route Handler

// app/api/auth/[...nextauth]/route.ts
import { handlers } from '@/auth'

export const { GET, POST } = handlers

Middleware Protection

// middleware.ts
export { auth as middleware } from '@/auth'

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

Getting Session Data

In Server Components

// app/dashboard/page.tsx
import { auth } from '@/auth'
import { redirect } from 'next/navigation'

export default async function DashboardPage() {
  const session = await auth()

  if (!session) {
    redirect('/login')
  }

  return (
    <div>
      <h1>Welcome, {session.user?.name}</h1>
    </div>
  )
}

In Client Components

// components/user-menu.tsx
'use client'

import { useSession } from 'next-auth/react'

export function UserMenu() {
  const { data: session, status } = useSession()

  if (status === 'loading') {
    return <div>Loading...</div>
  }

  if (!session) {
    return <SignInButton />
  }

  return (
    <div>
      <span>{session.user?.name}</span>
      <SignOutButton />
    </div>
  )
}

Session Provider Setup

// app/providers.tsx
'use client'

import { SessionProvider } from 'next-auth/react'

export function Providers({ children }: { children: React.ReactNode }) {
  return <SessionProvider>{children}</SessionProvider>
}

// app/layout.tsx
import { Providers } from './providers'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

Sign In/Out Components

// components/auth-buttons.tsx
import { signIn, signOut } from '@/auth'

export function SignInButton() {
  return (
    <form
      action={async () => {
        'use server'
        await signIn('github')
      }}
    >
      <button type="submit">Sign in with GitHub</button>
    </form>
  )
}

export function SignOutButton() {
  return (
    <form
      action={async () => {
        'use server'
        await signOut()
      }}
    >
      <button type="submit">Sign out</button>
    </form>
  )
}

Middleware-Based Auth

Basic Pattern

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const protectedRoutes = ['/dashboard', '/settings', '/api/protected']
const authRoutes = ['/login', '/signup']

export function middleware(request: NextRequest) {
  const token = request.cookies.get('session')?.value
  const { pathname } = request.nextUrl

  // Redirect authenticated users away from auth pages
  if (authRoutes.some(route => pathname.startsWith(route))) {
    if (token) {
      return NextResponse.redirect(new URL('/dashboard', request.url))
    }
    return NextResponse.next()
  }

  // Protect routes
  if (protectedRoutes.some(route => pathname.startsWith(route))) {
    if (!token) {
      const loginUrl = new URL('/login', request.url)
      loginUrl.searchParams.set('callbackUrl', pathname)
      return NextResponse.redirect(loginUrl)
    }
  }

  return NextResponse.next()
}

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

With JWT Verification

// middleware.ts
import { NextResponse } from 'next/server'
import { jwtVerify } from 'jose'

const secret = new TextEncoder().encode(process.env.JWT_SECRET)

export async function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  try {
    const { payload } = await jwtVerify(token, secret)
    // Token is valid, continue
    return NextResponse.next()
  } catch {
    // Token is invalid
    return NextResponse.redirect(new URL('/login', request.url))
  }
}

Role-Based Access Control

Extending Session Types

// types/next-auth.d.ts
import { DefaultSession } from 'next-auth'

declare module 'next-auth' {
  interface Session {
    user: {
      role: 'user' | 'admin'
    } & DefaultSession['user']
  }
}

// auth.ts
export const { handlers, auth } = NextAuth({
  callbacks: {
    session: ({ session, token }) => ({
      ...session,
      user: {
        ...session.user,
        role: token.role,
      },
    }),
    jwt: ({ token, user }) => {
      if (user) {
        token.role = user.role
      }
      return token
    },
  },
})

Role-Based Component

// components/admin-only.tsx
import { auth } from '@/auth'
import { redirect } from 'next/navigation'

export async function AdminOnly({ children }: { children: React.ReactNode }) {
  const session = await auth()

  if (session?.user?.role !== 'admin') {
    redirect('/unauthorized')
  }

  return <>{children}</>
}

// Usage
export default async function AdminPage() {
  return (
    <AdminOnly>
      <AdminDashboard />
    </AdminOnly>
  )
}

Session Storage Options

JWT (Stateless)

// auth.ts
export const { auth } = NextAuth({
  session: { strategy: 'jwt' },
  // JWT stored in cookies, no database needed
})

Database Sessions

// auth.ts
import { PrismaAdapter } from '@auth/prisma-adapter'
import { prisma } from '@/lib/prisma'

export const { auth } = NextAuth({
  adapter: PrismaAdapter(prisma),
  session: { strategy: 'database' },
  // Sessions stored in database
})

Custom Login Page

// app/login/page.tsx
'use client'

import { signIn } from 'next-auth/react'
import { useSearchParams } from 'next/navigation'

export default function LoginPage() {
  const searchParams = useSearchParams()
  const callbackUrl = searchParams.get('callbackUrl') || '/dashboard'

  return (
    <div className="flex flex-col gap-4">
      <button
        onClick={() => signIn('github', { callbackUrl })}
        className="btn"
      >
        Sign in with GitHub
      </button>
      <button
        onClick={() => signIn('google', { callbackUrl })}
        className="btn"
      >
        Sign in with Google
      </button>
    </div>
  )
}

Security Best Practices

  1. Use HTTPS in production
  2. Set secure cookie flags (HttpOnly, Secure, SameSite)
  3. Implement CSRF protection (built into NextAuth)
  4. Validate redirect URLs to prevent open redirects
  5. Use environment variables for secrets
  6. Implement rate limiting on auth endpoints
  7. Hash passwords with bcrypt or argon2

Resources

For detailed patterns, see:

  • references/middleware-auth.md - Advanced middleware patterns
  • references/session-management.md - Session strategies
  • examples/nextauth-setup.md - Complete NextAuth.js setup

When not to use it

  • When requiring complex multi-tenant identity management
  • When implementing non-Next.js authentication systems

Prerequisites

Next.js applicationNextAuth.js v5 beta

Limitations

  • Requires manual configuration of environment variables for secrets
  • Limited to Next.js framework environments

How it compares

It provides standardized, pre-configured patterns for Next.js-specific auth integration rather than requiring manual implementation of custom session logic.

Compared to similar skills

auth-patterns side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
auth-patterns (this skill)77moReviewIntermediate
middleware-protection16moReviewIntermediate
reviewing-nextjs-16-patterns118moReviewIntermediate
better-auth59moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

middleware-protection

dadbodgeoff

Protect routes with Next.js middleware. Check authentication once, protect routes declaratively. Supports public routes, protected routes, and role-based access.

13

reviewing-nextjs-16-patterns

djankies

Review code for Next.js 16 compliance - security patterns, caching, breaking changes. Use when reviewing Next.js code, preparing for migration, or auditing for violations.

11106

better-auth

mrgoonie

Implement authentication and authorization with Better Auth - a framework-agnostic TypeScript authentication framework. Features include email/password authentication with verification, OAuth providers (Google, GitHub, Discord, etc.), two-factor authentication (TOTP, SMS), passkeys/WebAuthn support, session management, role-based access control (RBAC), rate limiting, and database adapters. Use when adding authentication to applications, implementing OAuth flows, setting up 2FA/MFA, managing user sessions, configuring authorization rules, or building secure authentication systems for web applications.

527

agentation

benjitaylor

Add Agentation visual feedback toolbar to a Next.js project

69

modern-javascript-patterns

sickn33

Master ES6+ features including async/await, destructuring, spread operators, arrow functions, promises, modules, iterators, generators, and functional programming patterns for writing clean, efficient JavaScript code. Use when refactoring legacy code, implementing modern patterns, or optimizing JavaScript applications.

25

route-handlers

davepoon

This skill should be used when the user asks to "create an API route", "add an endpoint", "build a REST API", "handle POST requests", "create route handlers", "stream responses", or needs guidance on Next.js API development in the App Router.

14

Search skills

Search the agent skills registry