🚀 Join the waitlist now! waitlist.floot.dev
LogoFlootdocs
AuthSocial

Google

Configure Google Sign-In for your Floot app on every supported platform.

The Google button is already on the sign-in and sign-up screens, next to email and password. What is missing is a Google Cloud project to point it at, and one flag.

Behind that single button are two different flows, chosen by platform rather than by configuration:

PlatformFlowHow it works
Android, iOSNativeThe google_sign_in plugin returns an identity token, which goes to Supabase directly
Web, macOS, Windows, LinuxBrowserSupabase Auth's /authorize endpoint opens in a browser, and a deep link brings the user back

Every example below uses the project from floot create my_app --org com.acme. Substitute your own.

Turn Google Sign-In on

Requires ENABLE_GOOGLE_SIGN_IN

Google Sign-In is off in a new project. Set `ENABLE_GOOGLE_SIGN_IN=true` in `.env.local` to use this section.

.env.local
ENABLE_GOOGLE_SIGN_IN=true

The flag decides whether the google_sign_in plugin is registered at all, so it is the native flow (Android and iOS) that stops dead without it: the button is still there, and tapping it fails with the generic "unexpected error" toast. The browser flow never touches the plugin, which is why Google sign-in can appear to work on macOS or Windows while doing nothing on a phone.

Both client ids, on every platform

This is the single most common way to get Google Sign-In half-working. When the flag is on, the app requires both OAUTH_GOOGLE_IOS_CLIENT_ID and OAUTH_GOOGLE_WEB_CLIENT_ID, on Android and on desktop too, not only on iOS.

A release build will not tell you

Dart strips its own asserts from release builds, and this check is one of them. Ship with one of the two variables empty and nothing crashes; sign-in just quietly never completes. Create both credentials in the console before you enable the flag.

Google Cloud Platform Setup

Create a new project

Google Cloud Console → Cloud overview (sidebar) → Dashboard → Create project

Create credentials

APIs & Services (sidebar) → Credentials → Create credentials → OAuth client ID

  • Application type > iOS
  • Name > give a meaningful name
  • Bundle ID > floot create already set it. For my_app --org com.acme it is com.acme.myApp, the project name camel-cased, which is also what OAUTH_APPLE_CLIENT_ID uses. To read it out of the project instead:
    • Open the ios folder of your Flutter project in Xcode (right click on the folder → Open in Xcode)
    • Runner (sidebar) → General (tab bar) → Runner (TARGETS sidebar) → Identity → Bundle Identifier
  • App Store ID and Team ID > only if the app is already published on the Apple App Store

→ Create

iOS needs a Web client id as well. Head to the Web tab once you are done here.

Locally, [auth.external.google].skip_nonce_check already ships true. On Supabase Cloud you have to enable Skip nonce check yourself, in the Google provider on the Supabase Dashboard.

This information is shown to the user when giving consent to your app. In particular, make sure you have set up links to your app's privacy policy and terms of service.

APIs & Services (sidebar) → OAuth consent screen → Fill needed infos

Floot App Setup

Which env file

.env.local and supabase/.env.local are the local-development files. Release builds read .env instead, which floot create does not write; see Building for release.

CFBundleURLTypes

iOS needs your Google iOS client id as a URL scheme, in reverse-DNS form: Apple's convention for URL types.

Copy your iOS Client ID from Google Cloud Console, which looks like this:

861823949799-vc35cprkp249096uujjn0vvnmcvjppkn.apps.googleusercontent.com

Remove the domain part: get rid of .apps.googleusercontent.com

861823949799-vc35cprkp249096uujjn0vvnmcvjppkn

Add the domain part back at the beginning, in reverse order:

com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn

Put it in ios/Runner/Info.plist, replacing the your_google_ios_REVERSED_client_id placeholder. It is the first of the two schemes there; the second is your deep-link scheme and must stay as it is.

ios/Runner/Info.plist
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string>
      <string>com.acme.myapp</string>
    </array>
  </dict>
</array>

The app's environment

.env.local
ENABLE_GOOGLE_SIGN_IN=true
OAUTH_GOOGLE_IOS_CLIENT_ID=861823949799-vc35cprkp249096uujjn0vvnmcvjppkn.apps.googleusercontent.com
OAUTH_GOOGLE_WEB_CLIENT_ID=861823949799-8p0vgc9ne7ok4h5r2j1qafd6b3ltmuo1.apps.googleusercontent.com

The iOS client id goes in unreversed here. Only Info.plist wants the reversed form.

The Supabase environment and config

Supabase authenticates as the Web client, not the iOS one, so the values it needs are the same on every platform.

supabase/.env.local
OAUTH_GOOGLE_WEB_CLIENT_ID=861823949799-8p0vgc9ne7ok4h5r2j1qafd6b3ltmuo1.apps.googleusercontent.com
OAUTH_GOOGLE_WEB_SECRET=GOCSPX-...
SB_AUTH_EXTERNAL_REDIRECT_URI=http://127.0.0.1:54321/auth/v1/callback
supabase/config.toml
[auth.external.google]
enabled = true

Everything else in that block is already wired to a variable: client_id to OAUTH_GOOGLE_WEB_CLIENT_ID, secret to OAUTH_GOOGLE_WEB_SECRET, redirect_uri to SB_AUTH_EXTERNAL_REDIRECT_URI. Fill the variables, leave the env(...) references alone.

Head to the Web tab and create the Web client if you have not already.

No deep link is involved on iOS: the sign-in sheet is native, so there is no browser to come back from.

On this page