Skip to content

Instantly share code, notes, and snippets.

@srestraj
Last active December 13, 2023 04:50
Show Gist options
  • Save srestraj/c61d0a025f53ab7f99bd875eace5cc84 to your computer and use it in GitHub Desktop.
Save srestraj/c61d0a025f53ab7f99bd875eace5cc84 to your computer and use it in GitHub Desktop.
Integrate Google Sign-in and One-tap with Nuxt.js

Integrate Google Sign-in (Popup method) with Nuxt.js - Works in Incognito mode as well

Nuxt 3 version here.
Add GSI client in your nuxt.config.js
export default {
  ...
  head: {
    ...
    script: [
      {
        src: 'https://accounts.google.com/gsi/client',
      },
    ],
    ...
  }
  ...
}
In your login page or component, add the Google Button div (this will be populated by the rendered button)
<div id="googleButton"></div>
Inside your mounted hook, initialize the Google Sign in and render the Sign in button
<template>
  <div id="googleButton"></div>
</template>
<script>

export default {
  mounted() {
    // initialize Google Sign in  
    google.accounts.id.initialize({
        client_id: 'YOUR_CLIENT_ID',
        callback: this.handleCredentialResponse, //method to run after user clicks the Google sign in button
        context: 'signin'
      })
    
    // render button
    google.accounts.id.renderButton(
      document.getElementById('googleButton'),
      { 
        type: 'standard',
        size: 'large',
        text: 'signin_with',
        shape: 'rectangular',
        logo_alignment: 'center',
        width: 250
      }
    )
  },
  
  methods: {
    handleCredentialResponse(response) {
    
      // call your backend API here
      
      // the token can be accessed as: response.credential
    }
  }
}
</script>
If you also want the Google One-tap sign in, use the following inside the component or page you want to display one-tap.
<template>
...
</template>
<script>
  export default {
    mounted() {
      google.accounts.id.initialize({
        client_id: 'YOUR_CLIENT_ID',
        callback: this.handleCredentialResponse,
        context: 'signin',
      })
      google.accounts.id.prompt()
    },
    
    methods: {
      handleCredentialResponse(response) {
        // handle API calls same as above
      }
    }
  }
</script>
@srestraj
Copy link
Author

Hi @Daewon25 , once you get back the response from the callback, you'd need to pass it to backend for handling. However, if you want to extract the user details from the token you receive in the frontend itself and pass them to the backend, you can do that using jwt-decode.

For example:

<script>
import jwt_decode from 'jwt-decode'

export default {
    ...
  
  methods: {
    handleCredentialResponse(response) {      
      // the token can be accessed as: response.credential
      const token = jwt_decode(response.credential)
      console.log(`ID: ${token.sub}`)
      console.log(`Full Name: ${token.name}`)
      console.log(`Given Name: ${token.given_name}`)
      console.log(`Family Name: ${token.family_name}`)
      console.log(`Image URL: ${token.picture}`)
      console.log(`Email: ${token.email}`)
    }
  }
}
</script>

@Daewon25
Copy link

@srestraj thanks a lot!

@Fanreza
Copy link

Fanreza commented Jul 4, 2023

anyone have example without the google button?

@srestraj
Copy link
Author

srestraj commented Jul 7, 2023

@Fanreza, if you set the ux_mode to redirect and then handle the response server-side, you can create your own custom button. More about this here: https://developers.google.com/identity/gsi/web/reference/js-reference#ux_mode. You can also have a look at this for other options: https://developers.google.com/identity/gsi/web/reference/html-reference. If you want to use it with the pop_up mode itself, I think you can try hiding the default Google button with visibility: hidden or opacity: 0 and then add your custom button. Something like we do for custom file inputs. I haven't tried it myself, but it might work I think.

@Fanreza
Copy link

Fanreza commented Jul 10, 2023

@Fanreza, if you set the ux_mode to redirect and then handle the response server-side, you can create your own custom button. More about this here: https://developers.google.com/identity/gsi/web/reference/js-reference#ux_mode. You can also have a look at this for other options: https://developers.google.com/identity/gsi/web/reference/html-reference. If you want to use it with the pop_up mode itself, I think you can try hiding the default Google button with visibility: hidden and then add your custom button. Something like we do for custom file inputs. I haven't tried it myself, but it might work I think.

i think it will work, google button basically just a button right, we can programatically click it using javascript

@HalaSalim77
Copy link

hi, the login by google button is disapper suddenly and i got this error :

client:128 Uncaught Error
at _.$e (client:128:335)
at new sp (client:227:3)
at bq (client:246:34)
at Oo (client:244:246)
at Object.Po [as renderButton] (client:216:62)
at :8:24
at Object.insertBefore (93a0d79.js:2:45811)
at _ (93a0d79.js:2:59423)
at 93a0d79.js:2:58702
at m (93a0d79.js:2:58934)

what is the problem and how  i can fix it ?

@jirayuboss
Copy link

hi, the login by google button is disapper suddenly and i got this error :

client:128 Uncaught Error at _.$e (client:128:335) at new sp (client:227:3) at bq (client:246:34) at Oo (client:244:246) at Object.Po [as renderButton] (client:216:62) at :8:24 at Object.insertBefore (93a0d79.js:2:45811) at _ (93a0d79.js:2:59423) at 93a0d79.js:2:58702 at m (93a0d79.js:2:58934)

what is the problem and how  i can fix it ?

I also have the same issue. Did you find a way to fix it? Please help.

@srestraj
Copy link
Author

srestraj commented Aug 2, 2023

client:128 Uncaught Error
at _.$e (client:128:335)
at new sp (client:227:3)
at bq (client:246:34)
at Oo (client:244:246)
at Object.Po [as renderButton] (client:216:62)
at :8:24
at Object.insertBefore (93a0d79.js:2:45811)
at _ (93a0d79.js:2:59423)
at 93a0d79.js:2:58702
at m (93a0d79.js:2:58934)

Hi @HalaSalim77, could you send us the code snippet you have set up? Thanks.

@srestraj
Copy link
Author

srestraj commented Aug 4, 2023

Hi @HalaSalim77 and @jirayuboss , it looks like the issue is happening from the Google's side itself. As mentioned here: google/google-api-javascript-client#873 (comment), if you remove the width property or add px to it, it's fixed again. example:

google.accounts.id.renderButton(
      document.getElementById("gBtn"), {
        type: 'standard',
        size: 'large',
        text: 'signup_with',
        shape: 'pill',
        logo_alignment: 'left',
        width: '250px'
      }
)

I hope this helps.

@DwbpleaseCallMe
Copy link

Hello. I just want to display Google one tap on the website.

When I used your method to fix my nuxt2 project, there was no button on my website, but it was successful on other vue2 projects

//nuxt.config.js
{
src: 'https://accounts.google.com/gsi/client',
async: true,
defer: true,
},

//index.vue
mounted() {

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });
    window.google.accounts.id.prompt();


  }

}, 3000);

},

@srestraj
Copy link
Author

Hello. I just want to display Google one tap on the website.

When I used your method to fix my nuxt2 project, there was no button on my website, but it was successful on other vue2 projects

//nuxt.config.js { src: 'https://accounts.google.com/gsi/client', async: true, defer: true, },

//index.vue mounted() {

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });
    window.google.accounts.id.prompt();


  }

}, 3000);

},

@DwbpleaseCallMe, what's the error that you're seeing?

@DwbpleaseCallMe
Copy link

Hello. I just want to display Google one tap on the website.
When I used your method to fix my nuxt2 project, there was no button on my website, but it was successful on other vue2 projects
//nuxt.config.js { src: 'https://accounts.google.com/gsi/client', async: true, defer: true, },
//index.vue mounted() {

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });
    window.google.accounts.id.prompt();


  }

}, 3000);

},

@DwbpleaseCallMe, what's the error that you're seeing?

There was no error, it's just that there are no buttons displayed on the page

@srestraj
Copy link
Author

Hi @DwbpleaseCallMe, to display the button, you'd need to add the following as well.

setTimeout(() => {
  if (window.google && !this.token) {
    window.google.accounts.id.initialize({
      client_id: 'xxx',
      callback: this.handleGoogleOneTapCallback,
      context: 'signin',
    });

    // for button rendering
    window.google.accounts.id.renderButton(
      document.getElementById('googleButton'), // here, replace "googleButton" with the ID of your element that you want to populate with GSI.
      { 
        type: 'standard',
        size: 'large',
        text: 'signin_with',
        shape: 'rectangular',
        logo_alignment: 'center',
        width: '250px'
      }
    );
    window.google.accounts.id.prompt();


  }

}, 3000);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment