DEV Community

Cover image for What is NextAuth?
Himanay Khajuria
Himanay Khajuria

Posted on

What is NextAuth?

What is NextAuth and how to use it with Next.js and TypeScript

This beginner friendly guide explains what NextAuth is and shows how to set it up step-by-step in a Next.js + TypeScript project.

We will create a simple app that lets users sign in and sign out using GitHub OAuth.


1. What is NextAuth?

NextAuth.js is an authentication library made for Next.js.

It helps you add login systems easily without writing complex backend logic.

✅ Supports many providers: GitHub, Google, Facebook, etc.

✅ Handles sessions automatically

✅ Works with or without a database

✅ Easy to protect pages and APIs


2. Project overview

We will create a simple project with:

  • A home page (/)
  • A protected page (/protected)
  • GitHub login using NextAuth
  • Navbar with sign in / sign out buttons

Folder structure:

my-nextauth-app/
├─ .env.local
├─ next.config.js
├─ package.json
├─ tsconfig.json
├─ pages/
│  ├─ api/
│  │  └─ auth/
│  │     └─ [...nextauth].ts
│  ├─ _app.tsx
│  ├─ index.tsx
│  └─ protected.tsx
└─ components/
   └─ Navbar.tsx
Enter fullscreen mode Exit fullscreen mode

3. Create a Next.js TypeScript project

Open your terminal and run:

npx create-next-app@latest my-nextauth-app --typescript
cd my-nextauth-app
Enter fullscreen mode Exit fullscreen mode

4. Install NextAuth

Run this command:

npm install next-auth
Enter fullscreen mode Exit fullscreen mode

5. Setup environment variables

Create a file .env.local in your project root and add:

GITHUB_ID=your_github_client_id
GITHUB_SECRET=your_github_client_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_random_secret_key
Enter fullscreen mode Exit fullscreen mode

You can get GITHUB_ID and GITHUB_SECRET by creating an OAuth App on GitHub:

  1. Go to GitHub → Settings → Developer Settings → OAuth Apps
  2. Create a new app
  3. Set the Authorization callback URL to http://localhost:3000/api/auth/callback/github

6. Add NextAuth API route

Now, create a new file pages/api/auth/[...nextauth].ts and add this code:

import NextAuth from "next-auth";
import GithubProvider from "next-auth/providers/github";
import type { NextAuthOptions } from "next-auth";

export const authOptions: NextAuthOptions = {
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID || "",
      clientSecret: process.env.GITHUB_SECRET || "",
    }),
  ],
  session: {
    strategy: "jwt",
  },
  callbacks: {
    async jwt({ token, account, profile }) {
      if (account) {
        token.accessToken = account.access_token;
      }
      if (profile) {
        token.login = (profile as any).login; // Add GitHub username
      }
      return token;
    },
    async session({ session, token }) {
      session.accessToken = token.accessToken as string;
      (session.user as any).login = token.login;
      return session;
    },
  },
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
Enter fullscreen mode Exit fullscreen mode

7. Wrap the app with SessionProvider

In pages/_app.tsx, wrap your app with SessionProvider so that session data is available everywhere:

import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}: AppProps) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

8. Create Navbar component

Create a new file components/Navbar.tsx:

import { useSession, signIn, signOut } from "next-auth/react";

export default function Navbar() {
  const { data: session, status } = useSession();

  return (
    <nav
      style={{
        padding: "12px",
        borderBottom: "1px solid #ddd",
        display: "flex",
        justifyContent: "space-between",
        alignItems: "center",
      }}
    >
      <span style={{ fontWeight: "bold" }}>My App</span>

      {status === "loading" ? (
        <span>Loading...</span>
      ) : session ? (
        <div>
          <span style={{ marginRight: 12 }}>
            Signed in as {session.user?.name || (session.user as any).login}
          </span>
          <button onClick={() => signOut()}>Sign out</button>
        </div>
      ) : (
        <button onClick={() => signIn("github")}>Sign in with GitHub</button>
      )}
    </nav>
  );
}
Enter fullscreen mode Exit fullscreen mode

9. Create Home page

Open pages/index.tsx and add this:

import Navbar from "../components/Navbar";
import Link from "next/link";
import { useSession } from "next-auth/react";

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

  return (
    <div>
      <Navbar />
      <main style={{ padding: "16px" }}>
        <h1>Welcome to NextAuth Example</h1>
        {session ? (
          <>
            <p>Hello {session.user?.name || (session.user as any).login} 👋</p>
            <p>
              Go to your <Link href="/protected">Protected Page</Link>
            </p>
          </>
        ) : (
          <>
            <p>You are not signed in yet.</p>
            <p>Click “Sign in with GitHub” to continue.</p>
          </>
        )}
      </main>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

10. Create Protected page (client-side)

Create pages/protected.tsx:

import Navbar from "../components/Navbar";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";

export default function Protected() {
  const { data: session, status } = useSession();
  const router = useRouter();

  useEffect(() => {
    if (status === "unauthenticated") {
      router.push("/");
    }
  }, [status, router]);

  if (status === "loading") {
    return (
      <>
        <Navbar />
        <main style={{ padding: "16px" }}>Loading...</main>
      </>
    );
  }

  return (
    <>
      <Navbar />
      <main style={{ padding: "16px" }}>
        <h1>Protected Page</h1>
        <p>This page is only for signed-in users.</p>
        <p>Welcome {session?.user?.name || (session?.user as any).login}</p>
      </main>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

11. Create Server-side Protected page (optional)

If you want to protect a page on the server side, create pages/ssr-protected.tsx:

import Navbar from "../components/Navbar";
import { getSession } from "next-auth/react";
import type { GetServerSideProps } from "next";

export default function SSRProtected({ session }: any) {
  return (
    <>
      <Navbar />
      <main style={{ padding: "16px" }}>
        <h1>Server Side Protected Page</h1>
        <p>Hello {session.user?.name || session.user?.login}</p>
      </main>
    </>
  );
}

export const getServerSideProps: GetServerSideProps = async (context) => {
  const session = await getSession(context);

  if (!session) {
    return {
      redirect: {
        destination: "/",
        permanent: false,
      },
    };
  }

  return {
    props: { session },
  };
};
Enter fullscreen mode Exit fullscreen mode

12. How the authentication flow works

  1. The user clicks Sign in with GitHub.
  2. NextAuth redirects the user to GitHub OAuth.
  3. GitHub asks the user to authorize your app.
  4. GitHub sends the user back to your app with a token.
  5. NextAuth creates a session for the user.
  6. You can access user data using useSession() anywhere.

13. Common issues and fixes

GitHub login fails

✅ Check your GITHUB_ID, GITHUB_SECRET, and callback URL.

NEXTAUTH_SECRET missing

✅ Add NEXTAUTH_SECRET to your .env.local file.

Callback URL mismatch

✅ Make sure the callback URL in GitHub matches

http://localhost:3000/api/auth/callback/github.


14. Summary

  • NextAuth makes authentication easy in Next.js.
  • Supports multiple providers like GitHub, Google, etc.
  • Works both with and without databases.
  • Simple hooks: useSession, signIn, signOut.
  • Pages can be protected on the client or server side.

15. Quick setup steps

  1. npx create-next-app@latest my-nextauth-app --typescript
  2. npm install next-auth
  3. Add .env.local with GitHub credentials
  4. Create pages/api/auth/[...nextauth].ts
  5. Wrap your app with SessionProvider
  6. Use signIn and signOut in your Navbar
  7. Protect pages with useSession or getSession

🎉 You did it!

You now have a working Next.js + NextAuth + TypeScript project.

You can extend it by:

  • Adding Google login
  • Using Prisma or MongoDB for database sessions
  • Building a custom sign-in page
  • Managing user roles and permissions

Top comments (0)