useGoogleAuth
Authentication Hook
There are not many resources on Supabase Google authentication within React Native Expo apps. What I found was not well structured, in my opinion. For that reason, I built a hook from scratch to handle the process.
useGoogleAuth
1import * as QueryParams from "expo-auth-session/build/QueryParams";23import { useState } from "react";45import logError from "@/lib/logError";6import { supabase } from "@/lib/supabase";78import * as Linking from "expo-linking";9import * as WebBrowser from "expo-web-browser";1011WebBrowser.maybeCompleteAuthSession();1213type GoogleAuthError = {14code: string;15message: string;16};1718type GoogleAuthState = {19isLoading: boolean;20error: GoogleAuthError | null;21};2223export default function useGoogleAuth() {24const [state, setState] = useState<GoogleAuthState>({25isLoading: false,26error: null,27});2829const createSessionFromUrl = async (url: string) => {30try {31const { params, errorCode } = QueryParams.getQueryParams(url);3233if (errorCode) return { error: "An error occurred" };3435const { access_token, refresh_token } = params;36if (!access_token) return { error: "Something went wrong" };3738const { data, error } = await supabase.auth.setSession({39access_token,40refresh_token,41});4243if (error) return { error };44return { session: data.session };45} catch (error) {46logError("createSessionFromUrl", error);47return { error: "Session creation failed" };48}49};5051const performOAuth = async () => {52try {53const { data, error } = await supabase.auth.signInWithOAuth({54provider: "google",55options: {56redirectTo: Linking.createURL("/"),57skipBrowserRedirect: true,58queryParams: {59prompt: "select_account",60},61},62});6364if (error) return { error: "An error occurred" };65if (!data?.url) return { error: "Something went wrong" };6667const response = await WebBrowser.openAuthSessionAsync(68data.url,69Linking.createURL("/")70);7172if (response.type === "success" && response.url) {73await createSessionFromUrl(response.url);74}75return { error: "Authentication canceled or failed" };76} catch (error) {77logError("performOAuth", error);78return { error: "Authentication failed" };79}80};8182const handleGoogleAuth = async () => {83setState(prev => ({ ...prev, isLoading: true, error: null }));84const { error } = await performOAuth();85if (error) return setState(prev => ({ ...prev, isLoading: false, error: { code: "AUTH_ERROR", message: error } }));86else return setState(prev => ({ ...prev, isLoading: false }));87};8889return {90handleGoogleAuth,91isLoading: state.isLoading,92error: state.error,93};94}