* docs(react-native): create the basic expo project * docs(react-native): cross-platform Apple social sign-in * docs(react-native): cross-platform Google social sign-in * docs(react-native): fix typos * docs(react-native): remove wrong entry in the `Connection` component * Correct typos * Prettier * Draft * Draft * docs(react-native): use kebab-case file naming convention in Expo guide - use kebab-case file naming convention in Expo guide - add trailing semicolon to align with the standard Expo template conventions * docs(react-native): use kebab-case file naming convention in Expo social auth example * docs(react-native): update the packages of the Expo social auth example * Fix * Draft * Changes * Correct log message --------- Co-authored-by: Chris Chinchilla <chris.ward@supabase.io> Co-authored-by: Chris Chinchilla <chris@chrischinchilla.com>
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import { supabase } from '@/lib/supabase';
|
|
import { CredentialResponse, GoogleLogin, GoogleOAuthProvider } from '@react-oauth/google';
|
|
import { SignInWithIdTokenCredentials } from '@supabase/supabase-js';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import 'react-native-get-random-values';
|
|
|
|
export default function GoogleSignInButton() {
|
|
|
|
// Generate secure, random values for state and nonce
|
|
const [nonce, setNonce] = useState('');
|
|
const [sha256Nonce, setSha256Nonce] = useState('');
|
|
|
|
async function onGoogleButtonSuccess(authRequestResponse: CredentialResponse) {
|
|
console.debug('Google sign in successful:', { authRequestResponse })
|
|
if (authRequestResponse.clientId && authRequestResponse.credential) {
|
|
const signInWithIdTokenCredentials: SignInWithIdTokenCredentials = {
|
|
provider: 'google',
|
|
token: authRequestResponse.credential,
|
|
nonce: nonce,
|
|
}
|
|
|
|
const { data, error } = await supabase.auth.signInWithIdToken(signInWithIdTokenCredentials)
|
|
|
|
if (error) {
|
|
console.error('Error signing in with Google:', error)
|
|
}
|
|
|
|
if (data) {
|
|
console.log('Google sign in successful:', data)
|
|
}
|
|
}
|
|
}
|
|
|
|
function onGoogleButtonFailure() {
|
|
console.error('Error signing in with Google')
|
|
}
|
|
|
|
useEffect(() => {
|
|
function generateNonce(): string {
|
|
const array = new Uint32Array(1);
|
|
window.crypto.getRandomValues(array);
|
|
return array[0].toString();
|
|
};
|
|
|
|
async function generateSha256Nonce(nonce: string): Promise<string> {
|
|
const buffer = await window.crypto.subtle.digest('sha-256', new TextEncoder().encode(nonce));
|
|
const array = Array.from(new Uint8Array(buffer));
|
|
return array.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
}
|
|
|
|
let nonce = generateNonce();
|
|
setNonce(nonce);
|
|
|
|
generateSha256Nonce(nonce)
|
|
.then((sha256Nonce) => { setSha256Nonce(sha256Nonce) });
|
|
}, []);
|
|
|
|
return (
|
|
<GoogleOAuthProvider
|
|
clientId={process.env.EXPO_PUBLIC_GOOGLE_AUTH_WEB_CLIENT_ID ?? ''}
|
|
nonce={sha256Nonce}
|
|
>
|
|
<GoogleLogin
|
|
nonce={sha256Nonce}
|
|
onSuccess={onGoogleButtonSuccess}
|
|
onError={onGoogleButtonFailure}
|
|
useOneTap={true}
|
|
auto_select={true}
|
|
/>
|
|
</GoogleOAuthProvider>
|
|
);
|
|
} |