Google authentication with Expo & Supabase

Google authentication with Expo & Supabase

While building a mobile app for a SaaS, chances are you’re going to deal with social login sooner or later, and sometimes, this can be a little bit overwhelming.

However, the benefits of providing these additional mechanisms can drastically improve your users’ experience with the app. You can also request permission to access certain information about your users that could allow you to further tailor the experience based on personal preferences.

Popular social providers such as Google, Facebook, Twitter, and more, follow a common open standard known as OAuth, so the steps required to integrate each provider are similar.

Supabase to the rescue

Thankfully, if you are using Supabase as your database, you can easily add social login to your app,

In this article, we’ll focus on adding Google as our first social provider.

I highly recommend reading the previous article in the series first, which provides essential instructions for setting up your Supabase and Expo projects. Once you've gone through that article, you'll be fully prepared to dive into the upcoming content.

Here’s a link to the previous post

Creating a project in Google Cloud Platform

Before we can utilize Google as a social provider in your Expo app, it is essential to create a project in Google Cloud Platform. To set up your project, follow these steps:

  1. Visit cloud.google.com and sign in.
  2. Click on the dropdown at the top left corner.

    Google Cloud Console - Home

  3. Click on "New Project" at the top right corner.

    Google Cloud Console - Select project

  4. Fill in the form and click on "Create", and wait until the project is created. It could take a few seconds or even minutes.

    Warning: Once you confirm this form, you won’t be able to change your project id.

  5. Once the project creation is finished, you receive a notification like in the image below. Click “Select project” to set your new project as active, and you’ll be redirected to your new project’s dashboard.

    Google Cloud Console - Notification after finishing creating a project

    Google Cloud Console - New project dashboard

Creating the required OAuth Keys

  1. Once you are in your project’s dashboard, use the search box at the top to search for “OAuth consent screen”, and select the first result under “Products and Pages”

    Google Cloud Console - Searching for OAuth Consent Screen in the SearchBox

  2. In the User Type section, select “External” and hit “Create” to confirm

    Setting type of User for the OAuth Consent screen

  3. You’ll be redirected to the “Edit app registration” form. Make sure to review all the information and assets provided here, given that this information will be presented to your users during the login flow.

  4. While following the process, make sure to define your scopes based on your specific needs. Here you can see the full list of available scopes. Besides, add a few testing users so you can complete the auth flow in your app before publishing the Consent Screen.

    You can always come back and update your consent screen later. Also, make sure to publish the consent screen once your app is about to be submitted to the stores

    Option to Publish the OAuth Consent screen

Getting your Supabase callback URL

In the next step, we’ll need to create an OAuth client ID in Google Cloud. But first, we’ll need to get our callback URL from Supabase.

  1. Login into supabase, and go to your project’s dashboard.
  2. In the sidebar, click on the “Authentication” button

    Authentication button in Supabase Sidebar

  3. Under the “Configuration” section, click on “Providers” and click on “Google” to expand the accordion.

  4. Copy the provided Redirect URL.

Creating the OAuth client ID

  1. Back into cloud.google.com, visit your project dashboard.
  2. Click on the hamburger menu at the top left corner, and navigate to “APIs & Services” → “Credentials

    Access to credentials management in Google Cloud Console

  3. Click the “+ Create credentials” button, and then select “OAuth client ID

    Access to create a new OAuth client ID in Google Cloud Console

  4. Under “Application Type”, choose “Web application”. Fill in the name of your app, and click on “Add URI” under the “Authorized redirect URIs” section. Paste your Supabase redirect URL here.

    Authorized redirect URIs section in Google Cloud Console

  5. If everything goes right, you’ll get a “Client ID” and “Client Secret”. Make sure to store this information. You’ll need it in the next step.

Updating your Google tokens in your Supabase project

  1. Go back to your Supabase project, and click the “Authentication” button in the sidebar

    Authentication Button in Supabase Sidebar

  2. Select “Providers” → “Google

  3. Toggle the “Google Enabled” switch to ON
  4. Enter your Google tokens (Client id and Client Secret), and click on “Save

Adding social login to our Expo app

In the previous post, we created a SupabaseContext.tsx and a SupabaseProvider.tsx file.

  1. Let’s update the context by adding the getGoogleOAuthUrl and setOAuthSession methods:

    // context/SupabaseContext.tsx
    
    type SupabaseContextProps = {
      ...
    + getGoogleOAuthUrl: () => Promise<string | null>;
    + setOAuthSession: (tokens: {
    +   access_token: string;
    +   refresh_token: string;
    + }) => Promise<void>;
    };
    
    export const SupabaseContext = createContext<SupabaseContextProps>({
      ...
    + getGoogleOAuthUrl: async () => "",
    + setOAuthSession: async () => {},
    });
    
  2. Now, we need to also update the provider to implement this new method.

    A few things to mention here:

    • We are setting mysupabaseapp://auth as a redirect uri while calling the getGoogleOAuthUrl method. You need to replace mysupabaseapp with your custom scheme. In the next step, I’ll show you how to setup the same redirect URL in your Supabase project so everything works as expected.
    • The signInWithOAuth method will return an object that contains the Supabase URL that we need to start the auth flow in the browser later.
    • The setOAuthSession method will allow us to persist the user session using Supabase Auth. In that way, the user won’t need to sign in again the next time.

      A few things to mention here:

    • We are setting mysupabaseapp://auth as a redirect uri while calling the getGoogleOAuthUrl method. You need to replace mysupabaseapp with your custom scheme. In the next step, I’ll show you how to setup the same redirect URL in your Supabase project so everything works as expected.
    • The signInWithOAuth method will return an object that contains the Supabase URL that we need to start the auth flow in the browser later.
    • The setOAuthSession method will allow us to persist the user session using Supabase Auth. In that way, the user won’t need to sign in again the next time.
    // context/SupabaseProvider.tsx
    
    export const SupabaseProvider = (props: SupabaseProviderProps) => {
    
     const supabase = createClient(
       ...
     );
     ...
    
    + const getGoogleOAuthUrl = async (): Promise<string | null> => {
    +   const result = await supabase.auth.signInWithOAuth({
    +     provider: "google",
    +     options: {
    +       redirectTo: "mysupabaseapp://google-auth",
    +     },
    +   });
    +   
    +   return result.data.url;
    + };
    
    + const setOAuthSession = async (tokens: {
    +   access_token: string;
    +   refresh_token: string;
    + }) => {
    +   const { data, error } = await supabase.auth.setSession({
    +     access_token: tokens.access_token,
    +     refresh_token: tokens.refresh_token,
    +   });
    +
    +   if (error) throw error;
    +
    +   setLoggedIn(data.session !== null);
    + };
    
     ...
    
     return (
       <SupabaseContext.Provider
         value={{
             ...
    +       getGoogleOAuthUrl,
    +       setOAuthSession
         }}
       >
         ...
       </SupabaseContext.Provider>
     );
    };
    
  3. Install the expo-web-browser package by running the following command

     npx expo install expo-web-browser
    
  4. Finally, we need to update our LoginScreen.tsx

    • We need to add a “Sign in with Google” button.
    • We are using expo-web-browser to load an in-app browser for the login flow.
    • As described in the Expo docs, we call WebBrowser.warmUpAsync() to load the browser in the background before the user taps the button to improve the user experience. You can learn more about this in this link
    • Once the user taps the button, the flow should look like this:
      • We get the Supabase OAuth URL
      • openAuthSessionAsync is called with the Supabase URL
      • The Google Consent Screen is shown.
      • Once the user completes the flow, the browser returns to the app with a URL
      • We extract the tokens from the URL.
      • Finally, we call setOAuthSession to persist the Supabase session.
      • Optional: We securely store the provider token for future use
    • For the UI, we are using SpiroKit, but feel free to use your own button.
    + import * as WebBrowser from "expo-web-browser";
    + import * as SecureStore from "expo-secure-store";
    
    const LoginScreen = () => {
    
     const { 
       login, 
    +  getGoogleOAuthUrl,
    +  setOAuthSession 
     } = useSupabase();
    
     ...
    
    + React.useEffect(() => {
    +   WebBrowser.warmUpAsync();
    +
    +   return () => {
    +     WebBrowser.coolDownAsync();
    +   };
    + }, []);
    
     ...
    
    + const onSignInWithGoogle = async () => {
    +   setLoading(true);
    +   try {
    +     const url = await getGoogleOAuthUrl();
    +     if (!url) return;
    + 
    +     const result = await WebBrowser.openAuthSessionAsync(
    +       url,
    +       "mysupabaseapp://google-auth?",
    +       {
    +         showInRecents: true,
    +       }
    +     );
    + 
    +     if (result.type === "success") {
    +       const data = extractParamsFromUrl(result.url);
    +
    +       if (!data.access_token || !data.refresh_token) return;
    +
    +       setOAuthSession({
    +         access_token: data.access_token,
    +         refresh_token: data.refresh_token,
    +       });
    +
    +       // You can optionally store Google's access token if you need it later
    +       SecureStore.setItemAsync(
    +         "google-access-token",
    +         JSON.stringify(data.provider_token)
    +       );
    +     }
    +   } catch (error) {
    +     // Handle error here
    +     console.log(error);
    +   } finally {
    +     setLoading(false);
    +   }
    + };
    
    + const extractParamsFromUrl = (url: string) => {
    +   const params = new URLSearchParams(url.split("#")[1]);
    +   const data = {
    +     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"),
    +   };
    +
    +   return data;
    + };
    
     return (
       <KeyboardAvoidingView
         ...
       >
         <ScrollView contentContainerStyle={{ flexGrow: 1 }}>
           <VStack safeAreaTop padding={4} flex={1}>
             <VStack space={4} marginTop={5} width="full" flex={1}>
                 ...
    +           <Button
    +             isDisabled={loading}
    +             onPress={() => onSignInWithGoogle()}
    +             marginBottom={5}
    +           >
    +             {loading ? "Loading..." : "Sign in with Google"}
    +           </Button>
             </VStack>
           </VStack>
         </ScrollView>
       </KeyboardAvoidingView>
     );
    };
    
    export default LoginScreen;
    

Redirect URL setup in Supabase

  1. Go to your project dashboard in Supabase.
  2. In the sidebar, click the “Authentication” button.
  3. Under the “Configuration” section, click on “URL Configuration”.
  4. In the “Redirect URLs” section, click the “Add URL”.

    URL Redirection config in Supabase

  5. Add your custom scheme.

    1. This should match with the scheme used in the previous step.

Final thoughts

If you are still here, congrats! Now you have an app with Social login.

It's worth mentioning that Supabase offers support for numerous providers, so if you require additional options, they have you covered.

By following the steps outlined in this article, you should be able to easily add more providers to your app. While each provider may have a few specific steps to follow, Supabase's documentation serves as an excellent starting point. To delve deeper, you can find more information here

Once you get the tokens to interact with each provider, you should be able to update the Supabase provider to get the login URL. The rest of the flow should be reusable as is.

I’ll probably cover more about this in the future, so if you have any questions or require additional assistance, please do not hesitate to reach out.