Login with Google
Supabase Auth supports Sign in with Google on the web, native Android applications and Chrome extensions.
Overview#
To support Sign in with Google you need to configure the Google provider in the Supabase dashboard for your project.
There are three general ways to use Sign in with Google, depending on the application you're building:
- Sign in on the web or in web-based apps
- Using an OAuth flow initiated by Supabase Auth using Google Identity Authorization with OAuth 2.0 for Web Server Applications.
- Using a personalized sign-in button or One Tap and automatic sign-in for users already logged in to their Google account.
- Sign in in native Android apps and Chrome extensions
In some cases you're able to use the OAuth flow within web-based native apps such as with React Native, Expo or other similar frameworks. It is best practice to use native Sign in with Google capabilities whenever possible.
Before you can use Sign in with Google, you need to obtain a Google Cloud Platform account and have a project ready or create a new one.
Using the OAuth flow for the web#
Sign in with Google's OAuth flow is designed for web or browser based sign in methods. It can be used in web-based apps as well as in websites, though sometimes it is worthwhile considering using One Tap login directly.
Behind the scenes, Supabase Auth uses the Google OAuth 2.0 APIs, which are OpenID Connect certified, to perform the authentication.
To initiate sign in, you can use the signInWithOAuth()
method from the Supabase JavaScript library:
_10supabase.auth.signInWithOAuth({_10 provider: 'google',_10})
This call takes the user to Google's consent screen. When the flow ends, the user's profile information is exchanged and validated with Supabase Auth before it redirects back to your web application with an access and refresh token representing the user's session.
You can additionally extract the provider_token
from the session (on initial login only) which is the OAuth 2.0 access token issued by Google that grants your application access to the Google services for the authenticated users. Please store this token in local storage, cookies or in your database or server.
Google does not send out a refresh token by default, so you will need to pass parameters like these to signInWithOAuth()
in order to extract the provider_refresh_token
:
_10const { data, error } = await supabase.auth.signInWithOAuth({_10 provider: 'google',_10 options: {_10 queryParams: {_10 access_type: 'offline',_10 prompt: 'consent',_10 },_10 },_10})
Configuration #
To use the OAuth 2.0 flow, you will require the following information:
- Obtain OAuth credentials for your Google Cloud project in the Credentials page of the console. When creating a new credential, choose Web application. In Authorized redirect URIs enter
https://<project-id>.supabase.co/auth/v1/callback
. This URL will be seen by your users, and you can customize it by configuring custom domains. - Configure the OAuth Consent Screen. This information is shown to the user when giving consent to your app. Within Authorized domains make sure you add your Supabase project's domain
<project-id>.supabase.co
. Configure the non-sensitive scopes by making sure the following ones are selected:.../auth/userinfo.email
,.../auth/userinfo.profile
,openid
. If you're selecting other sensitive scopes, your app may require additional verification. In those cases, it's best to use custom domains. - Finally, add the client ID and secret from step 1 in the Google provider on the Supabase Dashboard.
Using native sign in#
Unlike the OAuth flow which requires the use of a web browser, the native Sign in with Google flow on Android uses the operating system's built-in functionalities to prompt the user for consent. Note that native sign-in has been rebranded as One Tap sign-in on Android by Google, which you should not confuse with One Tap sign in for web, as mentioned below.
When the user provides consent, Google issues an identity token (commonly abbreviated as ID token) that is then sent to your project's Supabase Auth server. When valid, a new user session is started by issuing an access and refresh token from Supabase Auth.
If you are building a Flutter app, you can use flutter_appauth package to sign a user into your Supabase project:
_90import 'dart:convert';_90import 'dart:math';_90import 'package:crypto/crypto.dart';_90import 'package:flutter_appauth/flutter_appauth.dart';_90import 'package:supabase_flutter/supabase_flutter.dart';_90_90/// Function to generate a random 16 character string._90String _generateRandomString() {_90 final random = Random.secure();_90 return base64Url.encode(List<int>.generate(16, (_) => random.nextInt(256)));_90}_90_90Future<AuthResponse> signInWithGoogle() {_90 // Just a random string_90 final rawNonce = _generateRandomString();_90 final hashedNonce =_90 sha256.convert(utf8.encode(rawNonce)).toString();_90_90 /// TODO: update the client ID with your own_90 ///_90 /// Client ID that you registered with Google Cloud._90 /// You will have two different values for iOS and Android._90 const clientId = 'YOUR_CLIENT_ID_HERE';_90_90 /// reverse DNS form of the client ID + `:/` is set as the redirect URL_90 final redirectUrl = '${clientId.split('.').reversed.join('.')}:/';_90_90 /// Fixed value for google login_90 const discoveryUrl =_90 'https://accounts.google.com/.well-known/openid-configuration';_90_90 final appAuth = FlutterAppAuth();_90_90 // authorize the user by opening the consent page_90 final result = await appAuth.authorize(_90 AuthorizationRequest(_90 clientId,_90 redirectUrl,_90 discoveryUrl: discoveryUrl,_90 nonce: hashedNonce,_90 scopes: [_90 'openid',_90 'email',_90 ],_90 ),_90 );_90_90 if (result == null) {_90 throw 'Could not find AuthorizationResponse after authorizing';_90 }_90_90 // Request the access and id token to google_90 final tokenResult = await appAuth.token(_90 TokenRequest(_90 clientId,_90 redirectUrl,_90 authorizationCode: result.authorizationCode,_90 discoveryUrl: discoveryUrl,_90 codeVerifier: result.codeVerifier,_90 nonce: result.nonce,_90 scopes: [_90 'openid',_90 'email',_90 ],_90 ),_90 );_90_90 final idToken = tokenResult?.idToken;_90_90 if (idToken == null) {_90 throw 'Could not find idToken from the token response';_90 }_90_90 return supabase.auth.signInWithIdToken(_90 provider: Provider.google,_90 idToken: idToken,_90 accessToken: tokenResponse?.accessToken,_90 nonce: rawNonce,_90 );_90}_90```_90_90In the Supabase JavaScript library, which you can use with web-based native frameworks like React Native or Expo, you can invoke this functionality like so:_90_90```ts_90await supabase.auth.signInWithIdToken({_90 provider: 'google',_90 token: '<identity token received from the OS>',_90 access_token: '<access token received from the OS>'_90})
Please take a look at these open-source projects which may help you obtain an ID token directly from the OS:
For apps written in Kotlin, please consult the community maintained library.
Configuration #
- Configure OAuth credentials for your Google Cloud project in the Credentials page of the console. When creating a new OAuth client ID, choose Android or iOS depending on the mobile operating system your app is built for.
- For Android, use the instructions on screen to provide the SHA-1 certificate fingerprint used to sign your Android app.
- For iOS, use the instructions on screen to provide the app Bundle ID, and App Store ID and Team ID if the app is already published on the Apple AppStore.
- Configure the 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.
- Finally, add the client ID from step 1 in the Google provider on the Supabase Dashboard, under Authorized Client IDs.
Note that you do not have to configure the OAuth flow in the Supabase Dashboard in order to use native sign in.
Using native sign in for Chrome extensions#
Similar to the native sign in for Android, you can use the Chrome browser's identity APIs to launch an authentication flow.
First, you need to configure your manifest.json
file like so:
_10{_10 "permissions": ["identity"],_10 "oauth2": {_10 "client_id": "<client ID>",_10 "scopes": ["openid", "email", "profile"]_10 }_10}
Then you should call the chrome.identity.launchWebAuthFlow()
function to trigger the sign in flow. On success, call the supabase.auth.signInWithIdToken()
function to complete sign in with your Supabase project.
_30const manifest = chrome.runtime.getManifest()_30_30const url = new URL('https://accounts.google.com/o/oauth2/auth')_30_30url.searchParams.set('client_id', manifest.oauth2.client_id)_30url.searchParams.set('response_type', 'id_token')_30url.searchParams.set('access_type', 'offline')_30url.searchParams.set('redirect_uri', `https://${chrome.runtime.id}.chromiumapp.org`)_30url.searchParams.set('scope', manifest.oauth2.scopes.join(' '))_30_30chrome.identity.launchWebAuthFlow(_30 {_30 url: url.href,_30 interactive: true,_30 },_30 async (redirectedTo) => {_30 if (chrome.runtime.lastError) {_30 // auth was not successful_30 } else {_30 // auth was successful, extract the ID token from the redirectedTo URL_30 const url = new URL(redirectedTo)_30 const params = new URLSearchParams(url.hash)_30_30 const { data, error } = await supabase.auth.signInWithIdToken({_30 provider: 'google',_30 token: params.get('id_token'),_30 })_30 }_30 }_30)
Configuration #
You will need to configure a client ID for your Chrome extension:
- Configure OAuth credentials for your Google Cloud project in the Credentials page of the console. When creating a new OAuth client ID, choose Chrome extension for the application type. For Item ID provide the unique ID of your Chrome extension. You can get this by calling
chrome.runtime.id
within the extension, or from the Web Store URL of the extension. For example, the Google Translate extension has the Web Store URLhttps://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb
and the last partaapbdbdomjkkjkaonfhkkikfgjllcleb
is its unique ID. - Configure the OAuth Consent Screen. This information is shown to the user when giving consent to your app.
- Finally, add the client ID from step 1 in the Google provider on the Supabase Dashboard, under Authorized Client IDs.
Note that you do not have to configure the OAuth flow in the Supabase Dashboard to sign in with Google inside Chrome extensions.
Using personalized sign-in buttons, One Tap or automatic sign-in#
Most web apps and websites can utilize Google's personalized sign-in buttons, One Tap or automatic sign-in for the best user experience.
Under the hood, these sign in methods end with an identity token being issued by Sign in with Google for Web. You can then use the supabase.auth.signInWithIdToken()
method to immediately issue an access and refresh tokens for the user, without needing to build any additional UIs or flows.
To get started, you can use the HTML Code Generator to customize the look, feel, features and behavior of the Sign in with Google button. Make sure you pick the Swap to JavaScript callback option and name the function that will receive a CredentialResponse
when sign in completes.
For example, this HTML code shows a typical Sign in with Google button:
_20<div_20 id="g_id_onload"_20 data-client_id="<client ID>"_20 data-context="signin"_20 data-ux_mode="popup"_20 data-callback="handleSignInWithGoogle"_20 data-nonce=""_20 data-auto_select="true"_20 data-itp_support="true"_20></div>_20_20<div_20 class="g_id_signin"_20 data-type="standard"_20 data-shape="pill"_20 data-theme="outline"_20 data-text="signin_with"_20 data-size="large"_20 data-logo_alignment="left"_20></div>
When the user signs in, the handleSignInWithGoogle
function will be called:
_10async function handleSignInWithGoogle(response) {_10 const { data, error } = await supabase.auth.signInWithIdToken({_10 token: response.credential,_10 nonce: 'NONCE', // must be the same one as provided in data-nonce (if any)_10 })_10}
Use of nonce is recommended, though optional. Make sure each nonce is generated randomly and available both in the data-nonce
attribute as well as in the handleSignInWithGoogle
callback function; otherwise the ID token will not be accepted.
Important Note on Nonce Validation#
Supabase Auth expects the nonce in Google's ID token to be hashed (specifically with SHA-256 and represented as a hexadecimal string).
To succeed with nonce validation, you will need to provide a hashed version of the nonce to Google and the non-hashed version to the signInWithIdToken
method.
The following code snippet provides an example of how to create both versions in a web application:
_17// Adapted from https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string_17_17import crypto from 'crypto'_17_17// ..._17_17const nonce = crypto.randomBytes(16).toString('base64') // Generate a random nonce_17const encoder = new TextEncoder()_17const encodedNonce = encoder.encode(nonce) // Encode the nonce_17const hash = await crypto.subtle.digest('SHA-256', encodedNonce) // Hash it with SHA-256_17const bytes = new Uint8Array(hash)_17const hashedNonce = Array.from(bytes)_17 .map((b) => b.toString(16).padStart(2, '0')) // Convert the hash to a hexadecimal string_17 .join('')_17_17// Use 'hashedNonce' when making the authentication request to Google_17// Use 'nonce' when invoking the supabase.auth.signInWithIdToken() method
Configuration #
- Obtain OAuth credentials for your Google Cloud project in the Credentials page of the console. When creating a new credential, choose Web application. As you're using the Google sign in button, you should configure the Authorized JavaScript origins and Authorized redirect URIs to the website where the buttons appear. You should not use your Supabase project domain name. For this use case, the client secret provided is not needed and can be ignored.
- Configure the 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.
- Finally, add the client ID from step 1 in the Google provider on the Supabase Dashboard under Authorized Client IDs.
Note that you do not have to configure the OAuth flow client ID and secret in the Supabase Dashboard when using this approach!