Files
supabase/examples/auth/expo-social-auth/components/social-auth-buttons/google/google-sign-in-button.tsx
MDL 3139f85b5d docs(react-native): Expo cross-platform social sign-in with complete example (#38178)
* 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>
2025-09-19 16:53:35 +02:00

127 lines
3.8 KiB
TypeScript

import { supabase } from '@/lib/supabase';
import { useEffect } from 'react';
import { TouchableOpacity } from 'react-native';
import { expo } from '@/app.json';
import { Text } from '@react-navigation/elements';
import { Image } from 'expo-image';
import * as WebBrowser from "expo-web-browser";
WebBrowser.maybeCompleteAuthSession();
export default function GoogleSignInButton() {
function extractParamsFromUrl(url: string) {
const parsedUrl = new URL(url);
const hash = parsedUrl.hash.substring(1); // Remove the leading '#'
const params = new URLSearchParams(hash);
return {
access_token: params.get("access_token"),
expires_in: parseInt(params.get("expires_in") || "0"),
refresh_token: params.get("refresh_token"),
token_type: params.get("token_type"),
provider_token: params.get("provider_token"),
code: params.get("code"),
};
};
async function onSignInButtonPress() {
console.debug('onSignInButtonPress - start');
const res = await supabase.auth.signInWithOAuth({
provider: "google",
options: {
redirectTo: `${expo.scheme}://google-auth`,
queryParams: { prompt: "consent" },
skipBrowserRedirect: true,
},
});
const googleOAuthUrl = res.data.url;
if (!googleOAuthUrl) {
console.error("no oauth url found!");
return;
}
const result = await WebBrowser.openAuthSessionAsync(
googleOAuthUrl,
`${expo.scheme}://google-auth`,
{ showInRecents: true },
).catch((err) => {
console.error('onSignInButtonPress - openAuthSessionAsync - error', { err })
console.log(err);
});
console.debug('onSignInButtonPress - openAuthSessionAsync - result', { result });
if (result && result.type === "success") {
console.debug('onSignInButtonPress - openAuthSessionAsync - success');
const params = extractParamsFromUrl(result.url);
console.debug('onSignInButtonPress - openAuthSessionAsync - success', { params });
if (params.access_token && params.refresh_token) {
console.debug('onSignInButtonPress - setSession');
const { data, error } = await supabase.auth.setSession({
access_token: params.access_token,
refresh_token: params.refresh_token,
});
console.debug('onSignInButtonPress - setSession - success', { data, error });
return;
} else {
console.error('onSignInButtonPress - setSession - failed');
// sign in/up failed
}
} else {
console.error('onSignInButtonPress - openAuthSessionAsync - failed');
}
}
// to warm up the browser
useEffect(() => {
WebBrowser.warmUpAsync();
return () => {
WebBrowser.coolDownAsync();
};
}, []);
return (
<TouchableOpacity
onPress={onSignInButtonPress}
style={{
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#ffffff',
borderWidth: 1,
borderColor: '#dbdbdb',
borderRadius: 4,
paddingVertical: 10,
paddingHorizontal: 15,
justifyContent: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 2, // For Android shadow
}}
activeOpacity={0.8}
>
<Image
source={{ uri: 'https://developers.google.com/identity/images/g-logo.png' }}
style={{ width: 24, height: 24, marginRight: 10 }}
/>
<Text
style={{
fontSize: 16,
color: '#757575',
fontFamily: 'Roboto-Regular', // Assuming Roboto is available; install via expo-google-fonts or similar if needed
fontWeight: '500',
}}
>
Sign in with Google
</Text>
</TouchableOpacity>
);
}