DEV Community

Murali Krishna
Murali Krishna

Posted on

Google One Tap login with Auth0

Assuming that you've created the project in the google developer console and configured the ClientID and ClientSecret in Auth0 under social connections. Let's see how you can enable login with Google One Tap using Auth0 and get the id_token


  1. Letting the user log in using Google One Tap
  2. Extract user email from the id_token by google
  3. Use the extracted email to sign in with Auth0

1. Letting the user log in using Google One Tap

Include the google script (login.html)

<script src="https://accounts.google.com/gsi/client"></script>
Enter fullscreen mode Exit fullscreen mode

Include the HTML tag to trigger one tap flow on page load

<div id="g_id_onload"
    data-client_id="GOOGLE_CLIENT_ID"
    data-context="signin"
    data-ux_mode="popup"
    data-callback="handleLogin"
    data-nonce=""
    data-close_on_tap_outside="false"
    data-itp_support="true">
</div>
Enter fullscreen mode Exit fullscreen mode

Google will use this tag as the configuration and triggers the one tap flow on load.

🚧 Google uses something called Exponential cool down, basically when ever you close the One Tap popup, it'll not show it again till the cool off period.
In order to see the popup, run this in the browser console and refresh the page

document.cookie = `g_state=;path=/;expires=Thu, 01 Jan 1970 00:00:01 GMT`;


2. Extract user email from the ID_TOKEN by google

There is a data-callback="handleLogin" attribute in the above, which will be called once the user logs in using the One Tap flow.

The parameter for the handleLogin will contain the token from Google.

The response will look like this

{
    "clientId": "YOUR_GOOGLE_CLIENT_ID",
    "client_id": "YOUR_GOOGLE_CLIENT_ID",
    "credential": "ID_TOKEN_WHICH_WILL_BE_A_JWT",
    "select_by": "user"
}
Enter fullscreen mode Exit fullscreen mode

Google will give us the id_token from which we need to extract the user email. Since it's in JWT format we can use some jwt decoding library to parse it.

function handleLogin(response) {
    const email = (jwt_decode(response.credential)).email;
}
Enter fullscreen mode Exit fullscreen mode

Decoded JWT should look something like this

{
  "iss": "https://accounts.google.com",
  "nbf": 1684674651,
  "aud": "YOUR_GOOGLE_CLIENT_ID",
  "sub": "105427290204744290733",
  "email": "USER_EMAIL",
  "email_verified": true,
  "azp": "YOUR_GOOGLE_CLIENT_ID",
  "name": "Shinchan Nohara",
  "picture": "https://lh3.googleusercontent.com/a/AGNmyxbMyc6kaGFYoe65-1eASeS6HwrIQt9HKD-qSyyp=s96-c",
  "given_name": "Shinchan",
  "family_name": "Nohara",
  "iat": 1684674951,
  "exp": 1684678551,
  "jti": "150ff9433d3511d76f10a443f8ab7beb94751477"
}
Enter fullscreen mode Exit fullscreen mode

3. Use the extracted email to sign in with Auth0

Now that we have the users email we can trigger the authorize call from Auth0. The problem is, if we trigger the authorize call normally it'll refresh the page which defeats the purpose of OneTap login. In order to avoid that we need to authorize with Auth0 using an iframe

For that we need to host the iframe.html at some path on your domain and inside the iframe.html we can call the authorize with the connection type as google-oauth2 and responseMode as web_message.

iframe.html

<html>

<head>
    <script src="https://cdn.auth0.com/js/auth0/9.18/auth0.min.js"></script>

    <script>
        const webAuth = new auth0.WebAuth({
            domain: 'YOUR_DOMAIN.auth0.com',
            clientID: 'AUTH0_CLIENT_ID'
        });

        // we need this message to receive the extracted
        // google email from the parent window
        window.addEventListener('message', (event) => {
            // verify if the `message.origin` matches to the 
            // original origin for security purposes
            webAuth.authorize({
                connection: 'google-oauth2',
                login_hint: event.data, // this is the email
                responseType: 'id_token',
                redirectUri: 'YOUR_DOMAIN.auth0.com/callback',
                responseMode: 'web_message',
                //Any additional options can go here
                params: { 'myAdditionalParam': 'something' }
            }, function (err, authResult) {
                console.log(err)
            });
        });
    </script>
</head>
</html>
Enter fullscreen mode Exit fullscreen mode

We need to load the iframe in login.html and pass the extracted user email from the Google response to Authorize. Once the authorization is completed the iframe will postMessage the token to the parent(login.html). We can add a message event listener to receive the token from the iframe.

login.html

function handleLogin(token) {
    const user_email = (jwt_decode(token.credential)).email;
    const iframe = document.getElementById("auth_iframe")
    iframe.src = "/iframe.html"
    iframe.onload = () => {
        iframe.contentWindow.postMessage(user_email);
    }
}

window.addEventListener("message", (event) => {
    // verify if the `message.origin` matches to the original 
    // origin for security purposes
    console.log(`Token: ${event.data.response.id_token}`)
    // Here you have the Auth0 id_token
}, false);
Enter fullscreen mode Exit fullscreen mode

🚀 Now you have the id_token

Top comments (0)