Auth

Login with Google


Supabase Auth supports Sign in with Google for the web, native Android applications, and Chrome extensions.

Prerequisites

Configuration

To support Sign In with Google, you need to configure the Google provider for your Supabase project.

For web applications, you can set up your signin button two different ways:

Application code configuration

To use your own application code:

  1. In the Google Cloud console, go to the Consent Screen configuration page. The consent screen is the view shown to your users when they consent to signing in to your app.

  2. Under Authorized domains, add your Supabase project's domain, which has the form <PROJECT_ID>.supabase.co.

  3. Configure the following non-sensitive scopes:

    • .../auth/userinfo.email
    • ...auth/userinfo.profile
    • openid
  4. Go to the API Credentials page.

  5. Click Create credentials and choose OAuth Client ID.

  6. For application type, choose Web application.

  7. Under Authorized JavaScript origins, add your site URL.

  8. Under Authorized redirect URLs, enter the callback URL from the Supabase dashboard. Expand the Google Auth Provider section to display it.

  9. When you finish configuring your credentials, you will be shown your client ID and secret. Add these to the Google Auth Provider section of the Supabase Dashboard.

Google pre-built configuration

To use Google's pre-built signin buttons:

  1. In the Google Cloud console, go to the Consent Screen configuration page. The consent screen is the view shown to your users when they consent to signing in to your app.
  2. Configure the screen to your liking, making sure you add links to your app's privacy policy and terms of service.
  3. Go to the API Credentials page.
  4. Click Create credentials and choose OAuth Client ID.
  5. For application type, choose Web application.
  6. Under Authorized JavaScript origins and Authorized redirect URLs, add your site URL. This is the URL of the website where the signin button will appear, not your Supabase project domain.
  7. When you finish configuring your credentials, you will be shown your client ID. Add this to the Authorized Client IDs field in the Google Auth Provider section of the Supabase Dashboard. Leave the OAuth client ID and secret blank. You don't need them when using Google's pre-built approach.

Signing users in

Application code

To use your own application code for the signin button, call the signInWithOAuth method (or the equivalent for your language).


_10
supabase.auth.signInWithOAuth({
_10
provider: 'google',
_10
})

For an implicit flow, that's all you need to do. The user will be taken to Google's consent screen, and finally redirected to your app with an access and refresh token pair representing their session.

For a PKCE flow, for example in Server-Side Auth, you need an extra step to handle the code exchange. When calling signInWithOAuth, provide a redirectTo URL which points to a callback route. This redirect URL should be added to your redirect allow list.

In the browser, signInWithOAuth automatically redirects to the OAuth provider's authentication endpoint, which then redirects to your endpoint.


_10
await supabase.auth.signInWithOAuth({
_10
provider,
_10
options: {
_10
redirectTo: `http://example.com/auth/callback`,
_10
},
_10
})

At the callback endpoint, handle the code exchange to save the user session.

Create a new file at app/auth/callback/route.ts and populate with the following:

app/auth/callback/route.ts

_30
import { NextResponse } from 'next/server'
_30
// The client you created from the Server-Side Auth instructions
_30
import { createClient } from '@/utils/supabase/server'
_30
_30
export async function GET(request: Request) {
_30
const { searchParams, origin } = new URL(request.url)
_30
const code = searchParams.get('code')
_30
// if "next" is in param, use it as the redirect URL
_30
const next = searchParams.get('next') ?? '/'
_30
_30
if (code) {
_30
const supabase = createClient()
_30
const { error } = await supabase.auth.exchangeCodeForSession(code)
_30
if (!error) {
_30
const forwardedHost = request.headers.get('x-forwarded-host') // original origin before load balancer
_30
const isLocalEnv = process.env.NODE_ENV === 'development'
_30
if (isLocalEnv) {
_30
// we can be sure that there is no load balancer in between, so no need to watch for X-Forwarded-Host
_30
return NextResponse.redirect(`${origin}${next}`)
_30
} else if (forwardedHost) {
_30
return NextResponse.redirect(`https://${forwardedHost}${next}`)
_30
} else {
_30
return NextResponse.redirect(`${origin}${next}`)
_30
}
_30
}
_30
}
_30
_30
// return the user to an error page with instructions
_30
return NextResponse.redirect(`${origin}/auth/auth-code-error`)
_30
}

After a successful code exchange, the user's session will be saved to cookies.

Saving Google tokens

The tokens saved by your application are the Supabase Auth tokens. Your app might additionally need the Google OAuth 2.0 tokens to access Google services on the user's behalf.

On initial login, you can extract the provider_token from the session and store it in a secure storage medium. The session is available in the returned data from signInWithOAuth (implicit flow) and exchangeCodeForSession (PKCE flow).

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
})

Google pre-built

Most web apps and websites can utilize Google's personalized sign-in buttons, One Tap or automatic sign-in for the best user experience.

  1. Load the Google client library in your app by including the third-party script:


    _10
    <script src="https://accounts.google.com/gsi/client" async></script>

  2. Use the HTML Code Generator to customize the look, feel, features and behavior of the Sign in with Google button.

  3. Pick the Swap to JavaScript callback option, and input the name of your callback function. This function will receive a CredentialResponse when sign in completes.

    To make your app compatible with Chome's third-party-cookie phase-out, make sure to set data-use_fedcm_for_prompt to true.

    Your final HTML code might look something like this:


    _21
    <div
    _21
    id="g_id_onload"
    _21
    data-client_id="<client ID>"
    _21
    data-context="signin"
    _21
    data-ux_mode="popup"
    _21
    data-callback="handleSignInWithGoogle"
    _21
    data-nonce=""
    _21
    data-auto_select="true"
    _21
    data-itp_support="true"
    _21
    data-use_fedcm_for_prompt="true"
    _21
    ></div>
    _21
    _21
    <div
    _21
    class="g_id_signin"
    _21
    data-type="standard"
    _21
    data-shape="pill"
    _21
    data-theme="outline"
    _21
    data-text="signin_with"
    _21
    data-size="large"
    _21
    data-logo_alignment="left"
    _21
    ></div>

  4. Create a handleSignInWithGoogle function that takes the CredentialResponse and passes the included token to Supabase. The function needs to be available in the global scope for Google's code to find it.


    _10
    async function handleSignInWithGoogle(response) {
    _10
    const { data, error } = await supabase.auth.signInWithIdToken({
    _10
    provider: 'google',
    _10
    token: response.credential,
    _10
    })
    _10
    }

  5. (Optional) Configure a nonce. The use of a nonce is recommended for extra security, but optional. The nonce should be generated randomly each time, and it must be provided in both the data-nonce attribute of the HTML code and the options of the callback function.


    _10
    async function handleSignInWithGoogle(response) {
    _10
    const { data, error } = await supabase.auth.signInWithIdToken({
    _10
    provider: 'google',
    _10
    token: response.credential,
    _10
    nonce: '<NONCE>',
    _10
    })
    _10
    }

    Note that the nonce should be the same in both places, but because Supabase Auth expects the provider to hash it (SHA-256, hexadecimal representation), you need to provide a hashed version to Google and a non-hashed version to signInWithIdToken.

    You can get both versions by using the in-built crypto library:


    _16
    // Adapted from https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string
    _16
    _16
    const nonce = btoa(
    _16
    String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))),
    _16
    );
    _16
    const encoder = new TextEncoder();
    _16
    const encodedNonce = encoder.encode(nonce);
    _16
    crypto.subtle.digest("SHA-256", encodedNonce).then((hashBuffer) => {
    _16
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    _16
    const hashedNonce = hashArray
    _16
    .map((b) => b.toString(16).padStart(2, "0"))
    _16
    .join("");
    _16
    }
    _16
    _16
    // Use 'hashedNonce' when making the authentication request to Google
    _16
    // Use 'nonce' when invoking the supabase.auth.signInWithIdToken() method