Authentication Flows with Auth.js (NextAuth v5) and OAuth Providers

Modern web applications require secure, reliable, and frictionless authentication mechanisms. Traditional custom-built authentication systems involve complex database schema designs for password hashing, session cookies, CSRF protection, and token expiration logic—areas prone to security vulnerabilities if implemented incorrectly.

Auth.js (formerly known as NextAuth.js) completely revolutionizes authentication in the Next.js ecosystem. Version 5 introduces a streamlined architecture, native support for server actions, Edge runtime compatibility, and robust modular providers.

This comprehensive guide explores how to integrate Auth.js v5 into Next.js applications, configure secure OAuth providers like Google and GitHub, manage user sessions, and handle custom credential callbacks.

Understanding the NextAuth Architecture

Auth.js provides a comprehensive solution specifically tailored for Next.js applications, offering several key advantages over alternative authentication libraries:

• Zero-Config Database Adapters: Seamlessly integrate with PostgreSQL, MongoDB, Prisma, and MySQL to persist user accounts, sessions, and verification tokens automatically.

• Edge Compatibility: Built natively for modern serverless architectures and Edge functions, ensuring lightning-fast session verification.

• Built-in Security: Handles token rotation, secure cookie encryption, PKCE flows for OAuth providers, and cross-site request forgery protection out of the box.

Setting Up Auth.js in Next.js

To begin, install the latest Auth.js package for Next.js via your preferred terminal package manager.

BASH
Installing Auth.js for Next.js.
npm install next-auth@beta

Next, configure your environment variables in `.env.local` to store your OAuth client credentials and secret keys securely.

ENV
Environment variables for Auth.js configuration.
AUTH_SECRET="your-super-secret-crypto-key"
AUTH_GOOGLE_ID="your-google-client-id"
AUTH_GOOGLE_SECRET="your-google-client-secret"
AUTH_GITHUB_ID="your-github-client-id"
AUTH_GITHUB_SECRET="your-github-client-secret"

Creating the NextAuth Configuration File

In Auth.js v5, you define your authentication handlers and providers in an `auth.ts` file and expose them through a Next.js API route catch-all endpoint.

TypeScript
Configuring Auth.js handlers and OAuth providers.
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import GitHub from 'next-auth/providers/github';

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [Google, GitHub],
  pages: {
    signIn: '/login',
  },
  callbacks: {
    session({ session, token }) {
      if (session.user && token.sub) {
        session.user.id = token.sub;
      }
      return session;
    },
  },
});

Next, expose these handlers via the App Router catch-all route at `app/api/auth/[...nextauth]/route.ts`.

TypeScript
Exporting GET and POST handlers for Auth.js.
import { handlers } from '@/auth';

export const { GET, POST } = handlers;

Accessing User Sessions on Client and Server

Auth.js provides utility functions to inspect authentication status across Server Components, Client Components, and Middleware.

TSX
Accessing session data inside a React Server Component.
import { auth, signIn, signOut } from '@/auth';

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

  if (!session) {
    return (
      <div className="p-8 text-center">
        <h1 className="text-2xl font-bold mb-4">Access Denied</h1>
        <form
          action={async () => {
            'use server';
            await signIn('google');
          }}
        >
          <button type="submit" className="px-4 py-2 bg-indigo-600 text-white rounded-lg">
            Sign in with Google
          </button>
        </form>
      </div>
    );
  }

  return (
    <div className="p-8">
      <h1 className="text-3xl font-bold">Welcome back, {session.user?.name}</h1>
      <p className="text-gray-600 mt-2">Email: {session.user?.email}</p>
      <form
        action={async () => {
          'use server';
          await signOut();
        }}
        className="mt-6"
      >
        <button type="submit" className="px-4 py-2 bg-red-600 text-white rounded-lg">
          Sign Out
        </button>
      </form>
    </div>
  );
}

Summary

Auth.js (NextAuth v5) simplifies secure application authentication by providing native OAuth provider integration, robust session management, and Edge-ready architecture.

By implementing structured configuration files, utilizing server actions for sign-in flows, and leveraging token callbacks, developers can build secure, scalable authentication workflows with minimal friction.