Setting up authentication is one of those tasks that sounds simple until you actually do it. If you’re building a Next.js 14+ app and want a secure, production-ready login flow, NextAuth Google OAuth is one of the fastest paths to get there. In this tutorial, we walk through the full integration from creating credentials in Google Cloud Console to protecting your dashboard routes with session checks.
By the end of this guide, you’ll have a working Google sign-in flow in less than 30 minutes.
Why Choose NextAuth.js for Google OAuth?
NextAuth.js (now also known as Auth.js) is the de facto authentication library for Next.js. It handles the complex parts of OAuth 2.0 so you can focus on your product.
- Built for Next.js: native support for the App Router and Server Components
- Secure by default: signed JWTs, CSRF protection, and encrypted cookies
- Provider-agnostic: Google, GitHub, credentials, and dozens more
- Database optional: works with or without an adapter

What You’ll Need Before Starting
| Requirement | Version / Details |
|---|---|
| Node.js | 18.17 or newer |
| Next.js | 14+ (App Router) |
| NextAuth.js | v5 (Auth.js) |
| Google Account | Access to Google Cloud Console |
Step 1: Create Your Next.js Project
If you don’t have a Next.js app yet, spin one up:
npx create-next-app@latest my-auth-app
cd my-auth-app
npm install next-auth@beta
We’re using next-auth v5 since it’s fully aligned with the App Router and Server Actions.
Step 2: Configure Google OAuth Credentials in Google Cloud Console
This is the part most developers get stuck on. Follow these steps carefully.
- Go to Google Cloud Console and create a new project (or select an existing one).
- In the left menu, navigate to APIs & Services > OAuth consent screen.
- Choose External user type, fill in your app name, support email, and developer contact info.
- Go to APIs & Services > Credentials and click Create Credentials > OAuth client ID.
- Choose Web application as the application type.
- Under Authorized JavaScript origins, add:
http://localhost:3000 - Under Authorized redirect URIs, add:
http://localhost:3000/api/auth/callback/google - Click Create and copy your Client ID and Client Secret.
Important: For production, you’ll need to add your live domain (for example https://yourdomain.com) and its matching callback URL.
Step 3: Set Up Environment Variables
Create a .env.local file in the root of your project:
AUTH_SECRET=your_generated_secret_here
AUTH_GOOGLE_ID=your_google_client_id
AUTH_GOOGLE_SECRET=your_google_client_secret
NEXTAUTH_URL=http://localhost:3000
Generate a secure AUTH_SECRET with:
npx auth secret

Step 4: Create the NextAuth Configuration File
Create auth.ts in your project root:
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,
}),
],
callbacks: {
async session({ session, token }) {
if (token?.sub) session.user.id = token.sub
return session
},
},
})
Step 5: Add the API Route Handler
Create the file app/api/auth/[...nextauth]/route.ts:
import { handlers } from "@/auth"
export const { GET, POST } = handlers
That’s the entire API layer. NextAuth handles callbacks, sign-in, and sign-out endpoints automatically. github.com has a solid rundown on this.
Step 6: Build the Sign-In and Sign-Out UI
Create a component called components/AuthButtons.tsx:
import { signIn, signOut, auth } from "@/auth"
export async function SignIn() {
return (
<form action={async () => { "use server"; await signIn("google") }}>
<button type="submit">Sign in with Google</button>
</form>
)
}
export async function SignOut() {
return (
<form action={async () => { "use server"; await signOut() }}>
<button type="submit">Sign out</button>
</form>
)
}
Step 7: Access the Session in Your Pages
In any Server Component (for example app/page.tsx):
import { auth } from "@/auth"
import { SignIn, SignOut } from "@/components/AuthButtons"
export default async function Home() {
const session = await auth()
if (!session?.user) {
return <SignIn />
}
return (
<div>
<p>Welcome, {session.user.name}!</p>
<img src={session.user.image} alt="avatar" />
<SignOut />
</div>
)
}

Step 8: Protect Routes with Middleware
Create middleware.ts in your project root to guard specific paths:
export { auth as middleware } from "@/auth"
export const config = {
matcher: ["/dashboard/:path*", "/account/:path*"],
}
Any user hitting /dashboard or /account without a valid session will be redirected to the sign-in page automatically.
Common Pitfalls and How to Avoid Them
| Issue | Fix |
|---|---|
| redirect_uri_mismatch | Check that your callback URL in Google Cloud exactly matches /api/auth/callback/google |
| MissingSecret error | Make sure AUTH_SECRET is set in .env.local |
| Session is null in client component | Wrap the app with SessionProvider from next-auth/react |
| Works in dev, fails in production | Update NEXTAUTH_URL and add production callback URLs to Google Cloud |
Bonus: Persisting Users to a Database
If you want to store users, connect a database adapter (Prisma, Drizzle, MongoDB, and more). Install the adapter:
npm install @auth/prisma-adapter @prisma/client
Then update auth.ts:
import { PrismaAdapter } from "@auth/prisma-adapter"
import { prisma } from "@/lib/prisma"
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [Google],
session: { strategy: "jwt" },
})
FAQ
Is NextAuth.js free to use?
Yes. NextAuth.js (Auth.js) is fully open source and free for commercial use. There are no license fees or usage limits. js.org has a solid rundown on this.
Can I use NextAuth Google OAuth with a custom backend?
Absolutely. You can either use the built-in JWT strategy and forward tokens to your backend, or use the signIn callback to sync users with your own API.
What’s the difference between NextAuth v4 and v5?
Version 5 (also branded as Auth.js) is optimized for the App Router, uses Server Actions, and consolidates configuration into a single auth.ts file. If you’re starting fresh in 2026, always go with v5.
How do I add more providers alongside Google?
Add them to the providers array in auth.ts. For example, import GitHub from "next-auth/providers/github" and pass its credentials the same way.
Do I need a database to use Google OAuth with NextAuth?
No. By default, NextAuth uses JWT sessions stored in cookies, so no database is required. Add an adapter only if you need to persist users, accounts, or sessions.
Wrapping Up
You now have a fully functional NextAuth Google OAuth integration running on Next.js 14+. The setup is minimal, the code is production-grade, and you can extend it with more providers, database adapters, or role-based access control whenever needed.
At Box Software, we build modern web applications with battle-tested authentication flows. If your team needs help scaling a secure Next.js app, feel free to reach out. There’s a good explainer over at nextjsstarter.com.
