I am setting up an android app using rn & expo. I have supabase auth setup for my web app but am stuck trying to set it up on android. The google auth "Choose an account" prompt appears as expected, but when I select an account to login, my session state doesn't update in my console.log check:
useEffect(() => {
console.log('session changed...') //does not fire besides on initial null value
console.log(session) //does not fire besides on initial null value
}, [session])
For my setup I have...
Created Google OAuth Client ID in Google Cloud Console using $ cd android && ./gradlew signingReport
's 'debug' config SHA1 and the android package name in app.json
.
Configured my OAuth Consent Screen using my supabase url as an authorized domain.
Added my OAuth Client ID to the Google provider on the Supabase Dashboard, using a comma to separate from my web-app auth Client ID
Setup my Supabase login component (4):
import { AppState } from 'react-native'
import 'react-native-url-polyfill/auto'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { createClient } from '@supabase/supabase-js'
const YOUR_REACT_NATIVE_SUPABASE_ANON_KEY = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY
const YOUR_REACT_NATIVE_SUPABASE_URL = process.env.EXPO_PUBLIC_SUPABASE_PROJECT_URL
const supabaseUrl = YOUR_REACT_NATIVE_SUPABASE_URL
const supabaseAnonKey = YOUR_REACT_NATIVE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
storage: AsyncStorage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
},
})
// Tells Supabase Auth to continuously refresh the session automatically
// if the app is in the foreground. When this is added, you will continue
// to receive 'onAuthStateChange' events with the 'TOKEN_REFRESHED' or
// 'SIGNED_OUT' event if the user's session is terminated. This should
// only be registered once.
AppState.addEventListener('change', (state) => {
if (state === 'active') {
supabase.auth.startAutoRefresh()
} else {
supabase.auth.stopAutoRefresh()
}
})
Added my session state in my app (6):
import 'react-native-url-polyfill/auto'
import { useState, useEffect } from 'react'
import { supabase } from './lib/supabase'
import Auth from './components/Auth'
import { View, Text } from 'react-native'
import { Session } from '@supabase/supabase-js'
export default function App() {
const [session, setSession] = useState<Session | null>(null)
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session)
})
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session)
})
}, [])
//...
}
Setup my auth signup button:
import {
GoogleSignin,
GoogleSigninButton,
statusCodes,
} from '@react-native-google-signin/google-signin'
import { supabase } from '../hooks/supabase'
import { Pressable } from 'react-native'
import AntDesign from '@expo/vector-icons/AntDesign';
const webClientId = process.env.EXPO_PUBLIC_GOOGLE_AUTH_ANDROID_CLIENT_ID
export default function GoogleSigninButtonAndroid () {
GoogleSignin.configure({
scopes: ['https://www.googleapis.com/auth/drive.readonly'],
webClientId: webClientId,
})
return (
<Pressable
style={{
padding: 12,
marginTop: 4
}}
onPress={async () => {
try {
await GoogleSignin.hasPlayServices()
console.log('sign in pressed')
const userInfo = await GoogleSignin.signIn()
if (userInfo.data.idToken) {
console.log('signed in')
const { data, error } = await supabase.auth.signInWithIdToken({
provider: 'google',
token: userInfo.data.idToken,
})
console.log(error, data)
} else {
throw new Error('no ID token present!')
}
} catch (error: any) {
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
// user cancelled the login flow
} else if (error.code === statusCodes.IN_PROGRESS) {
// operation (e.g. sign in) is in progress already
} else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
console.log('play')
// play services not available or outdated
} else {
// some other error happened
}
}
}}
>
<AntDesign name="google" size={26} color="black" />
</Pressable>
)
}
Updated app.json to accomodate react-native-google-signin
:
{
"expo": {
"plugins": ["@react-native-google-signin/google-signin"],
"android": {
"googleServicesFile": "./google-services.json"
},
"ios": {
"googleServicesFile": "./GoogleService-Info.plist"
}
}
}
And rebuilt the app
npx expo prebuild --clean
, npx expo run:android && npx expo run:ios
I am expecting the supabase auth session state to populate when I select an account on my google auth popup, but it does not change.
This worked for me! I used the wrong SHA1 when setting up Google OAuth Client ID in Google Cloud Console. $ cd android && ./gradlew signingReport
gives you the right SHA1, use debug variant when running npx expo run:android
I found the solution here: React-native google signin gives Developer Error