Skip to content
GitHub Twitter

How to implement google one-tap login with javascript and firebase

How to implement google one-tap login with javascript and firebase

Google One Tap is a new feature that allows users to create an account or log in to the website with a single click. It is also known as YOLO (You Only Login Once).

The login widget appears as a popup, and it will prompt the users to sign in or sign up with the existing Google account when any of these conditions are true:

  • You are logged in to your Gmail account,
  • You've signed in to your Chrome browser.

Implementation

Import the Google Client Script

You may ignore this if you already have the script included in your HTML head tag.

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

Initialize the OAuth Client

In order to initialize the Google oauth2 client you would need client id, you may grab it from here.

const client_id = "xxxxx.apps.googleusercontent.com"; // OAuth2 client id 

const handleCredentialResponse = response =>  console.log('response', response);
const nativeCallback = (obj) => console.log("native_callback!");
window.google.accounts.id.initialize({
    client_id,
    callback: handleCredentialResponse,
    auto_select: true,
    context: "use",
    native_callback: nativeCallback,
});

Prompt Signin Popup

window.google.accounts.id.prompt((notification) => {
    console.log("notification is: ", notification.getMomentType());
    if (notification.isDisplayMoment()) {
        console.log("IS DISPLAY MOMENT");
    }

    if (notification.isNotDisplayed()) {
        console.warn("one-tap did not show because:", notification.getNotDisplayedReason());
    }
    if (notification.isSkippedMoment()) {
        console.warn("one-tap skipped because:", notification.getSkippedReason());
    }
    if (notification.isDismissedMoment()) {
        console.warn("one-tap dismissed because:", notification.getDismissedReason());
    }
});

Above will prompt a signin popup with all logged in google accounts.

Integrate with Firebase

Import Firebase Client SDK

<script type="module">
    import {initializeApp} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
    import {getAnalytics} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-analytics.js";
    import {getAuth, GoogleAuthProvider, signInWithCredential} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";
    
    // Your web app's Firebase configuration
    // For Firebase JS SDK v7.20.0 and later, measurementId is optional
    const firebaseConfig = {
        apiKey: "AIzaSyB1NhaL............",
        authDomain: "your-project.firebaseapp.com",
        projectId: "your-project",
        storageBucket: "your-project.appspot.com",
        messagingSenderId: "123456789",
        appId: "1:123456789:web:54899c03b2574b182bcf5c",
        measurementId: ""
    };

    // Initialize Firebase
    const app = initializeApp(firebaseConfig);
    const auth = getAuth(app);
    const analytics = getAnalytics(app);
</script>

Now, Invoke firebase signInWithCredential method inside the above handleCredentialResponse function.

const handleCredentialResponse = (response) => {
    console.log(response);
    
    const credential = signInWithCredential(auth, GoogleAuthProvider.credential(response.credential))
        .then((result) => {
            console.log(result);
            const {user} = result;

            console.log(user.accessToken); // firebase JWT token
        })
        .catch((error) => {
            console.error("firebase error", error);
        });
    };

Complete Example

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

<script type="module">
  import {initializeApp} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
  import {getAnalytics} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-analytics.js";
  import {getAuth, GoogleAuthProvider, signInWithCredential} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";

  // Your web app's Firebase configuration
  // For Firebase JS SDK v7.20.0 and later, measurementId is optional
  const firebaseConfig = {
    apiKey: "AIzaSyCCEtLAGEE7UciGe-uSCzUG9to1Qc1T1HU",
    authDomain: "test-project-d1fb7.firebaseapp.com",
    projectId: "test-project-d1fb7",
    storageBucket: "test-project-d1fb7.appspot.com",
    messagingSenderId: "672309028889",
    appId: "1:672309028889:web:0f6870c75a46aaedc86288",
    measurementId: "G-FDB679M570"
  };

  // Initialize Firebase
  const app = initializeApp(firebaseConfig);
  const auth = getAuth(app);
  const analytics = getAnalytics(app);


  if (window.google) {
    showOneTapLogin();
  } else {
    const googleScript = document.getElementById('google-gsi-script');
    googleScript.addEventListener('load', () => {
      showOneTapLogin();
    })
  }

  function showOneTapLogin() {
    const client_id = "672309028889-bd1ohksd1ia1utns37leborm8o6au41s.apps.googleusercontent.com"; // OAuth2 client id

    const handleCredentialResponse = response => {
      console.log('response', response);
      const credential = signInWithCredential(auth, GoogleAuthProvider.credential(response.credential))
        .then((result) => {
          console.log(result);
          const {user} = result;

          console.log(user.accessToken); // firebase JWT token
        })
        .catch((error) => {
          console.error("firebase error", error);
        });
    };

    const nativeCallback = (obj) => console.log("native_callback!");
    window.google.accounts.id.initialize({
      client_id,
      callback: handleCredentialResponse,
      auto_select: true,
      context: "use",
      native_callback: nativeCallback,
    });
    window.google.accounts.id.prompt((notification) => {
      console.log("notification is: ", notification.getMomentType());
      if (notification.isDisplayMoment()) {
        console.log("IS DISPLAY MOMENT");
      }

      if (notification.isNotDisplayed()) {
        console.warn("one-tap did not show because:", notification.getNotDisplayedReason());
      }
      if (notification.isSkippedMoment()) {
        console.warn("one-tap skipped because:", notification.getSkippedReason());
      }
      if (notification.isDismissedMoment()) {
        console.warn("one-tap dismissed because:", notification.getDismissedReason());
      }
    });
  }
</script>