Set Up Google Authentication with NextAuth in Next.js
NextAuth makes it easy to integrate third-party authentication providers like Google. This guide walks you through setting up Google Sign-In in your Next.js app using the Google Provider. You'll learn how to handle OAuth flow, manage sessions, and store user data securely in MongoDB. It's a great option if you want a smooth sign-in experience with minimal user input.
1. Add the Signin Form
You can add signin form or any button which you want user click on it to signin by Google provider.
You can refer my Signin Form Component in my docs.
You can copy the simple Google signin button
jsximport GoogleIcon from "@/components/ui/icons/GoogleIcon"; ... <button className="flex w-full items-center justify-center gap-3 rounded-full bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:ring-transparent"> <GoogleIcon /> <span className="text-sm/6 font-semibold">Google</span> </button>
Google svg
jsxconst GoogleIcon = () => { return ( <svg viewBox="0 0 24 24" aria-hidden="true" className="h-4 w-4"> <path d="M12.0003 4.75C13.7703 4.75 15.3553 5.36002 16.6053 6.54998L20.0303 3.125C17.9502 1.19 15.2353 0 12.0003 0C7.31028 0 3.25527 2.69 1.28027 6.60998L5.27028 9.70498C6.21525 6.86002 8.87028 4.75 12.0003 4.75Z" fill="#EA4335" /> <path d="M23.49 12.275C23.49 11.49 23.415 10.73 23.3 10H12V14.51H18.47C18.18 15.99 17.34 17.25 16.08 18.1L19.945 21.1C22.2 19.01 23.49 15.92 23.49 12.275Z" fill="#4285F4" /> <path d="M5.26498 14.2949C5.02498 13.5699 4.88501 12.7999 4.88501 11.9999C4.88501 11.1999 5.01998 10.4299 5.26498 9.7049L1.275 6.60986C0.46 8.22986 0 10.0599 0 11.9999C0 13.9399 0.46 15.7699 1.28 17.3899L5.26498 14.2949Z" fill="#FBBC05" /> <path d="M12.0004 24.0001C15.2404 24.0001 17.9654 22.935 19.9454 21.095L16.0804 18.095C15.0054 18.82 13.6204 19.245 12.0004 19.245C8.8704 19.245 6.21537 17.135 5.2654 14.29L1.27539 17.385C3.25539 21.31 7.3104 24.0001 12.0004 24.0001Z" fill="#34A853" /> </svg> ); }; export default GoogleIcon;
The UI like this

2. Setup Database
To save user info into DB, we need to connect MongoDB and create User model.
You can refer to my docs, setup DB for Credentials is a same as Google provider.
3. Setup environment variables
a. Setup NextAuth env
Create a file .evn and add these variables
jsonNEXTAUTH_SECRET="f798f8f2d4d72c3d4062ba69f5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" NEXTAUTH_DEBUG="true" NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET value you can use any the random string, but I recommend run by command
bashopenssl rand -base64 32
On the production site, you can set NEXTAUTH_DEBUG="false", and NEXTAUTH_URL is your app domain.
After setup values in the .evn file, I ofter create a new file appConfig.ts in the root of folder.
js/* eslint-disable import/no-anonymous-default-export */ export default { // NextAuth NEXTAUTH: { DEBUG: process.env.NEXTAUTH_DEBUG === "true", SECRET: process.env.NEXTAUTH_SECRET, URL: process.env.NEXTAUTH_URL, }, };
b. Setup Google cloud env
Signin to Google console cloud, then click Project button

You can select your project or create a new project for your app (if you are building a new app, you need to create a new project, each app corresponds to a project)

After select or create project, you scroll down then choose the API & Services options

Click on the credentials on the left navigation, then click create Create credentials button on the top navigation

After create OAuth client ID, you will see the waring "To create an OAuth client ID, you must first configure your consent screen", it means we need config the name, color, branding, ... for consent screen which after user click on the Google Signin Button (on your sign in form).
Click on the "Configure consent screen" button to config. You need add the App name, email, and domain, ...


At the same page, click on the Clients button on the left navigation

Then click on the Create clients button, then choose "Web application" option. Then name for client, and add the Authorized JavaScript origins

Then config the Authorized redirect URIs
Just same with Authorized JavaScript origins but add "/api/auth/callback/google" at the end

After all steps, we done for setup OAuth2 in Google Cloud, now we just copy the client ID and client secret into the .env file.
You can get two values on the left site of current page

The .evn file
jsonGOOGLE_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" GOOGLE_CLIENT_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Add to appConfig.ts file
js/* eslint-disable import/no-anonymous-default-export */ export default { // Google cloud GOOGLE_CLIENT: { ID: process.env.GOOGLE_CLIENT_ID, SECRET: process.env.GOOGLE_CLIENT_SECRET, }, };
Nice, we all done to config the OAuth2, Consent Screen in Google Cloud!
4. Setup API Auth codes
a. Install NextAuth lib
Install NextAuth lib
bashnpm install next-auth or yarn add next-auth
b. Setup some constant values
Create a new file /constants/auth.ts
jsexport const SIGN_IN_PROVIDERS = { CREDENTIALS: "credentials", EMAIL: "email", GOOGLE: "google", FACEBOOK: "facebook", GITHUB: "github", } as const;
Create a new file /constants/routes.ts
jsexport const ROUTES = { signIn: "/signin", };
c. Setup NexAuth API
Create a file /app/api/auth/[...nextauth]/route.ts
jsimport NextAuth, { AuthOptions } from "next-auth"; import GoogleProvider from "next-auth/providers/google"; import appConfig from "@/appConfig"; import { SIGN_IN_PROVIDERS } from "@/constants/auth"; import { ROUTES } from "@/constants/routes"; import UserDAO from "@/libs/db/dao/UserDAO"; import { IUser } from "@/types/user"; export const authOptions: AuthOptions = { debug: appConfig.NEXTAUTH.DEBUG, secret: appConfig.NEXTAUTH.SECRET, providers: [ GoogleProvider({ clientId: appConfig.GOOGLE_CLIENT.ID as string, clientSecret: appConfig.GOOGLE_CLIENT.SECRET as string, authorization: { params: { prompt: "consent", // Ensures the refresh token is sent every time access_type: "offline", // Required to get a refresh token from Google response_type: "code", }, }, }), ], pages: { signIn: ROUTES.signIn, // Custom sign-in page (not using the default of NextAuth sign in page) }, session: { strategy: "jwt", maxAge: 60 * 60 * 24, // session will be expired in 1 day, JWT callback will be trigger (in client will call API session for server) }, callbacks: { async jwt({ token, account, user }) { // Run first time when signin // In the second times, the account and user will be undifined if (account?.provider === SIGN_IN_PROVIDERS.GOOGLE) { token.id = account.id as string; token.provider = SIGN_IN_PROVIDERS.GOOGLE; token.user = user; (token.user as { firstName: string | null | undefined }).firstName = user.name; } return token; }, async session({ session, token }) { session.id = token.id; session.accessToken = token.accessToken as string; session.user = token.user as IUser; return session; }, async signIn({ user }) { // If user sign in by provider in first time, we save the user info into DB try { await UserDAO.createUser({ firstName: user.name!, lastName: "", email: user.email!, image: user.image!, signUpBy: SIGN_IN_PROVIDERS.GOOGLE, }); return true; } catch (error) { console.error("Error saving user to MongoDB when signin by providers***", error); return false; } }, }, }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
5. Combine Back-end API with Front-end UI
Just add handleClick function for Signin Button (we added on the step 1)
jsconst handleClickProvider = (e) => { e.preventDefault(); signIn(SIGN_IN_BY.PROVIDERS.GOOGLE); };

You can add callback URL, for after signin, browser will redirect to it.
jsconst handleClickProvider = (e) => { e.preventDefault(); signIn(SIGN_IN_BY.PROVIDERS.GOOGLE, { callbackUrl: ROUTES.homePage }); };