mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
docs(auth-google): use onReady in Next.js one-tap component example (#37227)
* Update auth-google.mdx * Update apps/docs/content/guides/auth/social-login/auth-google.mdx * prettier fix
This commit is contained in:
1 parent
e1cab2669d
commit
45e2d1b2d2
1 file changed
+57
-67
@@ -376,82 +376,72 @@ If you're integrating Google One-Tap with your Next.js application, you can refe
|
||||
|
||||
import Script from 'next/script'
|
||||
import { createClient } from '@/utils/supabase/client'
|
||||
import { CredentialResponse } from 'google-one-tap'
|
||||
import type { accounts, CredentialResponse } from 'google-one-tap'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
declare const google: { accounts: accounts }
|
||||
|
||||
// generate nonce to use for google id token sign-in
|
||||
const generateNonce = async (): Promise<string[]> => {
|
||||
const nonce = btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))))
|
||||
const encoder = new TextEncoder()
|
||||
const encodedNonce = encoder.encode(nonce)
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', encodedNonce)
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer))
|
||||
const hashedNonce = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
|
||||
|
||||
return [nonce, hashedNonce]
|
||||
}
|
||||
|
||||
const OneTapComponent = () => {
|
||||
const supabase = createClient()
|
||||
const router = useRouter()
|
||||
|
||||
// generate nonce to use for google id token sign-in
|
||||
const generateNonce = async (): Promise<string[]> => {
|
||||
const nonce = btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))))
|
||||
const encoder = new TextEncoder()
|
||||
const encodedNonce = encoder.encode(nonce)
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', encodedNonce)
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer))
|
||||
const hashedNonce = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
|
||||
const initializeGoogleOneTap = () => {
|
||||
console.log('Initializing Google One Tap')
|
||||
const [nonce, hashedNonce] = await generateNonce()
|
||||
console.log('Nonce: ', nonce, hashedNonce)
|
||||
|
||||
return [nonce, hashedNonce]
|
||||
// check if there's already an existing session before initializing the one-tap UI
|
||||
const { data, error } = await supabase.auth.getSession()
|
||||
if (error) {
|
||||
console.error('Error getting session', error)
|
||||
}
|
||||
if (data.session) {
|
||||
router.push('/')
|
||||
return
|
||||
}
|
||||
|
||||
/* global google */
|
||||
google.accounts.id.initialize({
|
||||
client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
|
||||
callback: async (response: CredentialResponse) => {
|
||||
try {
|
||||
// send id token returned in response.credential to supabase
|
||||
const { data, error } = await supabase.auth.signInWithIdToken({
|
||||
provider: 'google',
|
||||
token: response.credential,
|
||||
nonce,
|
||||
})
|
||||
|
||||
if (error) throw error
|
||||
console.log('Session data: ', data)
|
||||
console.log('Successfully logged in with Google One Tap')
|
||||
|
||||
// redirect to protected page
|
||||
router.push('/')
|
||||
} catch (error) {
|
||||
console.error('Error logging in with Google One Tap', error)
|
||||
}
|
||||
},
|
||||
nonce: hashedNonce,
|
||||
// with chrome's removal of third-party cookies, we need to use FedCM instead (https://developers.google.com/identity/gsi/web/guides/fedcm-migration)
|
||||
use_fedcm_for_prompt: true,
|
||||
})
|
||||
google.accounts.id.prompt() // Display the One Tap UI
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const initializeGoogleOneTap = () => {
|
||||
console.log('Initializing Google One Tap')
|
||||
window.addEventListener('load', async () => {
|
||||
const [nonce, hashedNonce] = await generateNonce()
|
||||
console.log('Nonce: ', nonce, hashedNonce)
|
||||
|
||||
// check if there's already an existing session before initializing the one-tap UI
|
||||
const { data, error } = await supabase.auth.getSession()
|
||||
if (error) {
|
||||
console.error('Error getting session', error)
|
||||
}
|
||||
if (data.session) {
|
||||
router.push('/')
|
||||
return
|
||||
}
|
||||
|
||||
/* global google */
|
||||
google.accounts.id.initialize({
|
||||
client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
|
||||
callback: async (response: CredentialResponse) => {
|
||||
try {
|
||||
// send id token returned in response.credential to supabase
|
||||
const { data, error } = await supabase.auth.signInWithIdToken({
|
||||
provider: 'google',
|
||||
token: response.credential,
|
||||
nonce,
|
||||
})
|
||||
|
||||
if (error) throw error
|
||||
console.log('Session data: ', data)
|
||||
console.log('Successfully logged in with Google One Tap')
|
||||
|
||||
// redirect to protected page
|
||||
router.push('/')
|
||||
} catch (error) {
|
||||
console.error('Error logging in with Google One Tap', error)
|
||||
}
|
||||
},
|
||||
nonce: hashedNonce,
|
||||
// with chrome's removal of third-party cookies, we need to use FedCM instead (https://developers.google.com/identity/gsi/web/guides/fedcm-migration)
|
||||
use_fedcm_for_prompt: true,
|
||||
})
|
||||
google.accounts.id.prompt() // Display the One Tap UI
|
||||
})
|
||||
}
|
||||
initializeGoogleOneTap()
|
||||
return () => window.removeEventListener('load', initializeGoogleOneTap)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Script src="https://accounts.google.com/gsi/client" />
|
||||
<div id="oneTap" className="fixed top-0 right-0 z-[100]" />
|
||||
</>
|
||||
)
|
||||
return <Script onReady={initializeGoogleOneTap} src="https://accounts.google.com/gsi/client" />
|
||||
}
|
||||
|
||||
export default OneTapComponent
|
||||
|
||||
Reference in new issue
Block a user