Prompt
How do I set up login with Google in Next.js?
Latest observation
The easiest way to set up “Login with Google” in Next.js is to use NextAuth.js (now often referred to as Auth.js). It handles OAuth, sessions, callbacks, and cookies for you.
1) Install NextAuth
npm install next-auth
2) Create a Google OAuth app
In the Google Cloud Console:
- Create a project
- Go to APIs & Services → Credentials
- Create an OAuth client ID
- Set the application type to Web application
- Add an authorized redirect URI:
For local dev:
http://localhost:3000/api/auth/callback/google
For production:
https://your-domain.com/api/auth/callback/google
Copy the Client ID and Client Secret.
3) Add environment variables
Create .env.local:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
NEXTAUTH_SECRET=some-random-secret
NEXTAUTH_URL=http://localhost:3000
You can generate a secret with:
openssl rand -base64 32
4) Create the NextAuth config
If you use the App Router (app/)
Create:
app/api/auth/[...nextauth]/route.js or .ts
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
const handler = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
secret: process.env.NEXTAUTH_SECRET,
});
export { handler as GET, handler as POST };
If you use the Pages Router (pages/)
Create:
pages/api/auth/[...nextauth].ts
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
secret: process.env.NEXTAUTH_SECRET,
});
5) Add a login button
App Router or Pages Router
Use signIn from NextAuth:
"use client";
import { signIn, signOut, useSession } from "next-auth/react";
export default function LoginButton() {
const { data: session } = useSession();
if (session) {
return (
<>
<p>Signed in as {session.user?.email}</p>
<button onClick={() => signOut()}>Sign out</button>
</>
);
}
return <button onClick={() => signIn("google")}>Sign in with Google</button>;
}
6) Wrap your app with SessionProvider
App Router
Create a client provider component, for example:
app/providers.tsx
"use client";
import { SessionProvider } from "next-auth/react";
export default function Providers({ children }: { children: React.ReactNode }) {
return <SessionProvider>{children}</SessionProvider>;
}
Then use it in app/layout.tsx:
import Providers from "./providers";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
Pages Router
Wrap your app in pages/_app.tsx:
import { SessionProvider } from "next-auth/react";
export default function App({ Component, pageProps }: any) {
return (
<SessionProvider session={pageProps.session}>
<Component {...pageProps} />
</SessionProvider>
);
}
7) Use the session anywhere
import { useSession } from "next-auth/react";
export default function Profile() {
const { data: session } = useSession();
if (!session) return <p>Not signed in</p>;
return <p>Welcome, {session.user?.name}</p>;
}
Common issues
Redirect URI mismatch
Make sure the redirect URI in Google Cloud exactly matches:
http://localhost:3000/api/auth/callback/google
NEXTAUTH_URL incorrect
Set it to your real app URL in production.
Missing SessionProvider
If useSession() doesn’t work, your app likely isn’t wrapped in SessionProvider.
Optional: protect pages/routes
If you want a page to require login, you can check the session on the client or server and redirect if not logged in.
If you want, I can give you:
- a full App Router example,
- a full Pages Router example, or
- a version with TypeScript + Prisma database persistence.