In this guide, we’ll implement Google One Tap Login in a modern web application using Better_Auth, Next.js, Prisma, and Shadcn. Google One Tap enables users to log in with minimal interaction, creating a seamless and user-friendly authentication experience. By the end of this tutorial, your application will support Google One Tap login, providing fast, secure, and passwordless authentication.
Tech Stack
Here’s the technology stack we’ll be using:
- Better_Auth v1: A lightweight and extensible TypeScript authentication library.
- Next.js: A powerful React framework for building server-rendered applications.
- Prisma: A modern ORM for efficient and type-safe database interaction.
- ShadCN: A utility-first component library for rapid UI development.
- TailwindCSS: A popular CSS framework for building modern user interfaces.
- Resend: A reliable email service for sending OTPs.
Prerequisites
Before proceeding, ensure you have the following ready:
- Node.js (LTS version) installed.
- A package manager like npm, yarn, or pnpm (we'll use
pnpm
in this guide). - A PostgreSQL database instance (local or hosted, such as Supabase or PlanetScale).
- If you're working locally, Docker is a great way to set this up.
- Familiarity with TypeScript, Next.js, and Prisma.
Cloning the Starter Project:
This guide builds upon functionality such as Email-Password Authentication and Email Verification. You can:
- Start from scratch by following these guides:
- Or, clone the starter project:
git clone -b feat-magiclink https://github.com/Daanish2003/better_auth_nextjs.git
Navigate to the project directory and install dependencies:
pnpm install
Setup
1. Configure the .env
File
Create a .env
file in the root of your project and add these configurations:
# Authentication settings
BETTER_AUTH_SECRET="your-secret-key" # Replace with a secure key
BETTER_AUTH_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Database settings
POSTGRES_PASSWORD="your-password"
POSTGRES_USER="your-username"
DATABASE_URL="postgresql://your-username:your-password@localhost:5432/mydb?schema=public"
# Resend API Key
RESEND_API_KEY="your-resend-api-key"
If you're using Docker for PostgreSQL, start the container:
docker compose up -d
Step 1: Get the ClientID for Google One Tap Login
- Go to the Google Cloud Console.
- Navigate to Credentials > Create Credentials > OAuth 2.0 Client IDs.
- Under Authorized JavaScript Origins, set the following:
- For local development:
http://localhost:3000
andhttp://localhost
- For production: Use your application's domain, e.g.,
https://example.com
.
- For local development:
- Scroll down to the Authorized Redirect URIs section and ensure you have a redirect URL configured, even if not directly used by Google One Tap, such as:
- Local:
http://localhost:3000/api/auth/callback/google
- Production:
https://example.com/api/auth/callback/google
.
- Local:
- Save the OAuth Client ID and Client Secret for later use.
Step 2: Setup Environment Variable
Open your .env file in your project folder and paste the google client ID in it
NEXT_PUBLIC_GOOGLE_CLIENT_ID="your-google-client-id"
Step 3: Update auth.ts and auth-client.ts file
Open auth.ts
file in your project folder and add oneTap()
function in the plugin array.
import { betterAuth } from "better-auth";
import { oneTap } from "better-auth/plugins"
export const auth = betterAuth({
appName: "better_auth_nextjs",
plugins: [
//other plugins
oneTap()
]
});
Then, Open auth-client.ts
file in your project folder and add oneTapClient()
function in the plugin array
// src/lib/auth-client.ts
import { passkeyClient, twoFactorClient } from "better-auth/plugins";
import { anonymousClient, magicLinkClient, oneTapClient, usernameClient } from "better-auth/client/plugins"
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_APP_URL,
plugins: [
// other plugins
oneTapClient({
// pass in the client ID of google from .env
clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID as string
})
]
})
export const {
signIn,
signOut,
signUp,
useSession
} = authClient;
Step 4: Create a oneTapCall()
function
Create a file named one-tap.ts
inside the folder /helpers/auth/
and paste the code from below
import { authClient } from "@/lib/auth-client";
export const oneTapCall = async () => {
try {
await authClient.oneTap({
callbackURL: '/', // redirect '/' route after login
cancelOnTapOutside: true, // cancel oneTap when user Taps outside the oneTap component
context: "signin", // signin or signup or use
autoSelect: true, // auto select the account to be true
});
} catch(error) {
console.log(error)
}
};
Step 5: Call the function inside signIn Component:
Open sign-in.tsx
file in your project folder and call the oneTapCall() function inside useEffect()
hook
"use client";
// other imports
import { oneTapCall } from "./one-tap";
const SignIn = () => {
// handle states for signin
// use useEffect hook call oneTap function wherever page reloads
useEffect(() => {
oneTapCall()
}, [])
// other function and logic of signIn component
return (
{/* SignIn Form */}
);
};
export default SignIn;
Step 6: Run your application:
Start your development server:
pnpm dev
Navigate to your sign-in
route and test the Magic Link Authentication flow. Enter your email, receive the magic link, and log in seamlessly by clicking the link.
At the top right corner of the page you will see the oneTap login option by google
Conclusion
Congratulations! 🎉 You’ve successfully implemented Magic Link Authentication in your application using Better_Auth, Next.js, Prisma, Resend, Shadcn, and TailwindCSS. This secure, user-friendly feature eliminates the need for traditional passwords, allowing users to authenticate effortlessly via a one-time email link.
With this modern authentication method, your app offers:
- Enhanced User Experience: Simplified, password-free login flow.
- Improved Security: Reduced risk of password theft and account compromise.
- Modern Standards: Aligning with the latest trends in authentication.
Your application is now equipped to provide a seamless and secure login experience, meeting the demands of today's users while ensuring robust security practices.
Top comments (1)
I was looking for something similar to use in my projects. Thanks for this!