
How to Add Google One Tap Sign-In to Your Next.js App
meocuteequas • Feb 16, 2025Ever wanted to make signing into your Next.js app as smooth as butter? Google One Tap is your answer! It lets users sign in with just a single click using their Google account. In this tutorial, I'll show you how to implement both Google One Tap and traditional Google Sign-In in your Next.js application using Auth.js (formerly NextAuth.js).
What We'll Build
By the end of this tutorial, your app will have:
- A sleek Google One Tap popup that appears automatically
- A traditional "Sign in with Google" button
- Proper session handling and user authentication
Getting Your Tools Ready
Before we dive in, make sure you have:
- A Next.js project up and running
- Auth.js installed (
npm install next-auth@beta
) - A Google Cloud Console project with OAuth credentials set up
Don't have these ready? No worries! Here's a quick guide to setting up Google OAuth credentials.
Let's Get Started!
1. Setting Up Auth.js Configuration
First, let's create our auth configuration. Create a new file called auth.config.ts
in your app
folder:
import type { NextAuthConfig } from "next-auth"; import GoogleProvider from "next-auth/providers/google"; export const authConfig: NextAuthConfig = { providers: [ Google, CredentialsProvider({ id: "googleonetap", name: "google-one-tap", credentials: { credential: { type: "text" }, }, async authorize(credentials) { const token = credentials.credential; const data = await fetchUserData(...); if (!data) return null; const { data: user } = data; const decoded = decodeAccessToken(user.access_token); return { ...decoded, ...user }; }, }) ] };
We're setting up two ways to sign in here:
- Traditional Google Sign-In
- Google One Tap (using our custom
googleonetap
provider)
2. Setting Up the Auth Provider
Next, we need to wrap our app with an auth provider. Create a new file for this app/context/auth-provider.tsx
:
"use client"; import { SessionProvider } from "next-auth/react"; export default function AuthProvider({ children }: { children: React.ReactNode }) { return <SessionProvider>{children}</SessionProvider>; }
Now, let's set up our main auth configuration app/auth.ts
:
export const { auth, handlers, signIn, signOut } = NextAuth({ ...authConfig, pages: { signIn: "/sign-in" }, callbacks: { async jwt({ token, user, account }) { if (user) { switch (account?.provider) { case "google": { const credential = account.id_token; const data = await fetchUserData(...); if (!data) return null; const { data: googleAccount } = data; const decoded = decodeAccessToken(googleAccount.access_token); token.access_token = googleAccount.access_token; token.refresh_token = googleAccount.refresh_token; break; } default: { token.access_token = user.access_token; token.refresh_token = user.refresh_token; } } } return token; }, async session({ session, token }) { return token ? { ...session, ...token } : session; }, }, });
And create the auth API route app/api/auth/[...nextauth]/route.ts
:
import { handlers } from "@/auth"; export const { GET, POST } = handlers;
3. Creating the Google One Tap Component
Here's where the magic happens! Let's create a component that handles the Google One Tap popup components/GoogleOneTap.tsx
:
"use client"; // Add type definition for Google One Tap declare global { interface Window { google: { accounts: { id: { initialize: (config: any) => void; prompt: (callback: (notification: any) => void) => void; cancel: () => void; revoke: (hint: string, callback: () => void) => void; }; }; }; } } export default function GoogleOneTap() { const searchParams = useSearchParams(); const { data: session } = useSession(); const [isGoogleScriptLoaded, setIsGoogleScriptLoaded] = useState(false); const handleCredentialResponse = useCallback( (response: any) => { signIn("googleonetap", { credential: response.credential, redirect: false, }) .then(() => { const redirectUrl = searchParams.get("callbackUrl") || "/"; window.location.href = redirectUrl; }) .catch((error) => { console.error("Error signing in:", error); }); }, [searchParams] ); // ... rest of the component implementation }
4. Adding It All Together
Now, let's add our Google One Tap component to the main layout app/layout.tsx
:
import AuthProvider from "@/context/auth-provider"; import GoogleOneTap from "@/components/GoogleOneTap"; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <AuthProvider> {children} <GoogleOneTap /> </AuthProvider> </body> </html> ); }
5. Creating the Sign-In Page
Let's create a simple sign-in page with a Google button app/sign-in/page.tsx
:
import { signIn } from "next-auth/react"; export default function SignIn() { return ( <div> <button onClick={() => signIn("google")} className="px-4 py-2 bg-blue-500 text-white rounded-md" > Sign in with Google </button> </div> ); }
6. Final Touch: Environment Variables
Create a .env.local
file in your project root /.env.local
:
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-google-client-id NEXT_PUBLIC_GOOGLE_CLIENT_SECRET=your-google-client-secret
Remember to replace these with your actual Google OAuth credentials!
Testing It Out
Once you've got everything set up:
- Start your development server (
npm run dev
) - Visit your site
- You should see the Google One Tap popup appear automatically
- Try clicking the "Sign in with Google" button on your sign-in page
Troubleshooting Tips
If you're not seeing the One Tap popup:
- Make sure your Google OAuth credentials are correct
- Check that you're using a real domain (One Tap doesn't work on localhost)
- Ensure you've enabled the Google People API in your Google Cloud Console
What's Next?
Now that you've got Google One Tap working, you might want to:
- Add loading states to your sign-in buttons
- Customize the One Tap popup appearance
- Add error handling for failed sign-in attempts
Conclusion
And there you have it! You've just added a super smooth sign-in experience to your Next.js app. Your users can now sign in with either Google One Tap or the traditional Google Sign-In button. Pretty cool, right?
Remember, good authentication UX can make or break your app, and Google One Tap is a great way to reduce friction in the sign-in process.
Happy coding! 🚀
Found this helpful? Don't forget to share it with other developers who might find it useful! If you run into any issues, feel free to drop a comment below.