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:
| Platform | Flow | How it works |
|---|---|---|
| Android, iOS | Native | The google_sign_in plugin returns an identity token, which goes to Supabase directly |
| Web, macOS, Windows, Linux | Browser | Supabase 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.
ENABLE_GOOGLE_SIGN_IN=trueThe 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 createalready set it. Formy_app --org com.acmeit iscom.acme.myApp, the project name camel-cased, which is also whatOAUTH_APPLE_CLIENT_IDuses. To read it out of the project instead:- Open the
iosfolder of your Flutter project in Xcode (right click on the folder →Open in Xcode) Runner(sidebar) →General(tab bar) →Runner(TARGETSsidebar) →Identity→Bundle Identifier
- Open the
- 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.
Setup OAuth consent screen
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.comRemove the domain part: get rid of .apps.googleusercontent.com
861823949799-vc35cprkp249096uujjn0vvnmcvjppknAdd the domain part back at the beginning, in reverse order:
com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppknPut 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.
<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
ENABLE_GOOGLE_SIGN_IN=true
OAUTH_GOOGLE_IOS_CLIENT_ID=861823949799-vc35cprkp249096uujjn0vvnmcvjppkn.apps.googleusercontent.com
OAUTH_GOOGLE_WEB_CLIENT_ID=861823949799-8p0vgc9ne7ok4h5r2j1qafd6b3ltmuo1.apps.googleusercontent.comThe 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.
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[auth.external.google]
enabled = trueEverything 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.