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.
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.
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.
app /components /CustomGoogleOneTap.tsx '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:
app /google-sign-in-example /page.tsx import { CustomGoogleOneTap } from '@/app/components/CustomGoogleOneTap'
export default function CustomOneTapPage ({ children } : { children : React . ReactNode }) {
return (
< CustomGoogleOneTap >
< h1 >Google One Tap Example</ h1 >
</ CustomGoogleOneTap >
)
}