Home

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:

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:


_10
supabase.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:


_10
const { 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:

  1. 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.
  2. 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.
  3. 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:


_90
import 'dart:convert';
_90
import 'dart:math';
_90
import 'package:crypto/crypto.dart';
_90
import 'package:flutter_appauth/flutter_appauth.dart';
_90
import 'package:supabase_flutter/supabase_flutter.dart';
_90
_90
/// Function to generate a random 16 character string.
_90
String _generateRandomString() {
_90
final random = Random.secure();
_90
return base64Url.encode(List<int>.generate(16, (_) => random.nextInt(256)));
_90
}
_90
_90
Future<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
_90
In 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
_90
await 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 #

  1. 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.
  1. 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.
  2. 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.


_30
const manifest = chrome.runtime.getManifest()
_30
_30
const url = new URL('https://accounts.google.com/o/oauth2/auth')
_30
_30
url.searchParams.set('client_id', manifest.oauth2.client_id)
_30
url.searchParams.set('response_type', 'id_token')
_30
url.searchParams.set('access_type', 'offline')
_30
url.searchParams.set('redirect_uri', `https://${chrome.runtime.id}.chromiumapp.org`)
_30
url.searchParams.set('scope', manifest.oauth2.scopes.join(' '))
_30
_30
chrome.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:

  1. 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 URL https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb and the last part aapbdbdomjkkjkaonfhkkikfgjllcleb is its unique ID.
  2. Configure the OAuth Consent Screen. This information is shown to the user when giving consent to your app.
  3. 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:


_10
async 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
_17
import crypto from 'crypto'
_17
_17
// ...
_17
_17
const nonce = crypto.randomBytes(16).toString('base64') // Generate a random nonce
_17
const encoder = new TextEncoder()
_17
const encodedNonce = encoder.encode(nonce) // Encode the nonce
_17
const hash = await crypto.subtle.digest('SHA-256', encodedNonce) // Hash it with SHA-256
_17
const bytes = new Uint8Array(hash)
_17
const 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 #

  1. 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.
  2. 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.
  3. 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!