Build a custom Google One Tap authentication flow
Google One Tap enables users to press a single button to authentication in your Clerk application with a Google account.
This guide will walk you through how to build a custom Google One Tap authentication flow.
Enable Google as a social connection
To use Google One Tap with Clerk, follow the steps in the dedicated guide to configure Google as a social connection in the Clerk Dashboard using custom credentials.
Create the Google One Tap authentication flow
To authenticate users with Google One Tap, you must:
- Initialize a "Sign In With Google" client UI, passing in your Client ID.
- Use the response to authenticate the user in your Clerk app if the request was successful.
- Redirect the user back to the page they started the authentication flow from by default, or to another URL if necessary.
The following example creates a component that implements a custom Google One Tap authentication flow, which can be used in a sign-in or sign-up page.
'use client'
import { useClerk } from '@clerk/nextjs'
import { useRouter } from 'next/navigation'
import Script from 'next/script'
import { useEffect } from 'react'
// Add clerk to Window to avoid type errors
declare global {
interface Window {
google: any
}
}
export function CustomGoogleOneTap({ children }: { children: React.ReactNode }) {
const clerk = useClerk()
const router = useRouter()
useEffect(() => {
// Will show the One Tap UI after two seconds
const timeout = setTimeout(() => oneTap(), 2000)
return () => {
clearTimeout(timeout)
}
}, [])
const oneTap = () => {
const { google } = window
if (google) {
google.accounts.id.initialize({
// Add your Google Client ID here.
client_id: 'xxx-xxx-xxx',
callback: async (response: any) => {
// Here we call our provider with the token provided by Google
call(response.credential)
},
})
// Uncomment below to show the One Tap UI without
// logging any notifications.
// return google.accounts.id.prompt() // without listening to notification
// Display the One Tap UI, and log any errors that occur.
return google.accounts.id.prompt((notification: any) => {
console.log('Notification ::', notification)
if (notification.isNotDisplayed()) {
console.log('getNotDisplayedReason ::', notification.getNotDisplayedReason())
} else if (notification.isSkippedMoment()) {
console.log('getSkippedReason ::', notification.getSkippedReason())
} else if (notification.isDismissedMoment()) {
console.log('getDismissedReason ::', notification.getDismissedReason())
}
})
}
}
const call = async (token: any) => {
try {
const res = await clerk.authenticateWithGoogleOneTap({
token,
})
await clerk.handleGoogleOneTapCallback(res, {
signInFallbackRedirectUrl: '/example-fallback-path',
})
} catch (error) {
router.push('/sign-in')
}
}
return (
<>
<Script src="https://accounts.google.com/gsi/client" strategy="beforeInteractive">
{children}
</Script>
</>
)
}
You can then display this component on any page. The following example demonstrates a page that displays this component:
import { CustomGoogleOneTap } from '@/app/components/CustomGoogleOneTap'
export default function CustomOneTapPage({ children }: { children: React.ReactNode }) {
return (
<CustomGoogleOneTap>
<h1>Google One Tap Example</h1>
</CustomGoogleOneTap>
)
}
Feedback
Last updated on