Vue 3 Google Login

npm  npm  npm 

Overview

This is a lightweight plugin to implement log-in and sign-up flows using Google Identity Servicesopen in new window with the help of Google 3P Authorization JavaScript Libraryopen in new window

This allows you to implement the following features

  • Login with Google button
  • Login using One Tap prompt
  • Automatic Login without any user interaction
  • Login with Google using a custom button

Prerequisites

  • This plugin needs vue version 3.0.3 or above to work properly
  • To enable Login With Google on your website, you first need to set up your Google API client ID. To do so, follow these stepsopen in new window
  • For testing in local evironment, you need to add http://localhost and
    http://localhost:<port_number> to the Authorized JavaScript origins

Basic Setup

Installation

First step is to install it using npm

npm install vue3-google-login

Or using yarn

yarn add vue3-google-login

Initialize the plugin

Initialize the vue3-google-login plugin in main.js, this will register a component GoogleLogin globally

import { createApp } from 'vue'
import App from './App.vue'
import vue3GoogleLogin from 'vue3-google-login'

const app = createApp(App)

app.use(vue3GoogleLogin, {
  clientId: 'YOUR_GOOGLE_CLIENT_ID'
})

app.mount('#app')

💡 If you dont want to initialize and register GoogleLogin component, you can directly import this from vue3-google-login package and use the client-id prop, also some functions accepts a clientId option which can be used to avoid initialising the plugin, see here for more info

GoogleLogin component

Once the plugin is installed you can use the component GoogleLogin anywhere in your project, this will render a log in button which opens a popup for Google login

<script setup>
const callback = (response) => {
  // This callback will be triggered when the user selects or login to
  // his Google account from the popup
  console.log("Handle the response", response)
}
</script>

<template>
  <GoogleLogin :callback="callback"/>
</template>

Here is an image showing log in button rendered by Google

One Tap prompt

For this feature set the prop prompt to true, this will open a prompt with the list of logged in Google accounts of the user, now user can just tap on his prefered account to easily login to your application

<script setup>
const callback = (response) => {
  // This callback will be triggered when user click on the One Tap prompt
  // This callback will be also triggered when user click on login button 
  // and selects or login to his Google account from the popup
  console.log("Handle the response", response)
}
</script>

<template>
  <GoogleLogin :callback="callback" prompt/>
</template>

Or use googleOneTap function

<script setup>
import { onMounted } from "vue"
import { googleOneTap } from "vue3-google-login"

onMounted(() => {
  googleOneTap()
    .then((response) => {
      // This promise is resolved when user selects an account from the the One Tap prompt
      console.log("Handle the response", response)
    })
    .catch((error) => {
      console.log("Handle the error", error)
    })
})

</script>

<template>
  <div>One-Tap prompt will be shown once this component is mounted</div>
</template>

ℹ️ If the user closes the One Tap prompt manually, the One Tap prompt will be suppressed, see hereopen in new window for more info

Here is an image showing One Tap prompt

Use of googleLogout function

While using One-tap feature, a dead-loop UX issueopen in new window may occur. To resolve this issue, in your logout function run googleLogout funtion

import { googleLogout } from "vue3-google-login"
const yourLogoutFunction() {
  // your logout logics
  googleLogout()
}

❗ Function googleLogout is used to temporarily disable One Tap Automatic sign-in for one day. This API does not sign out your users out of your website or any Google websites.

Automatic Login

To enable this feature, set the prop autoLogin to true, this will automatically detects whether only one Google account is logged in, if yes then prompt will automatically log in and will trigger the callback without any user interactions, to make this work prompt must be set to true

<script setup>
const callback = (response) => {
  // This callback will be triggered automatically 
  // if one single Google account is already logged in
  console.log("Handle the response", response)
}
</script>

<template>
  <GoogleLogin :callback="callback" prompt auto-login/>
</template>

Or use googleOneTap function and set autoLogin option to true

<script setup>
import { onMounted } from "vue"
import { googleOneTap } from "vue3-google-login"

onMounted(() => {
  googleOneTap({ autoLogin: true })
    .then((response) => {
      // This promise is resolved when user selects an account from the the One Tap prompt
      console.log("Handle the response", response)
    })
    .catch((error) => {
      console.log("Handle the error", error)
    })
})
</script>

<template>
  <div>One-Tap prompt will be shown once this component is mounted</div>
</template>

Here is an image showing how the prompt detects the logged in Google account and logs in automatically

Get User Data

In the triggered callback after login you will get a JWT credential string which can be decoded using decodeCredential function to retrive users basic data

<script setup>
import { decodeCredential } from 'vue3-google-login'
const callback = (response) => {
  // decodeCredential will retrive the JWT payload from the credential
  const userData = decodeCredential(response.credential)
  console.log("Handle the userData", userData)
}
</script>

<template>
  <GoogleLogin :callback="callback" prompt auto-login/>
</template>

❗ You cannot use decodeCredential function to retrive user data when you are using Custom Login Button, because it doesn't give a JWT credential, instead it gives an authorization code or access token, see here for more info

Custom Login Button

❗ For custom buttons this plugin use google.accounts.oauth2.initCodeClient and google.accounts.oauth2.initTokenClient under the hoods which gives OAuth2 authorization codeopen in new window and Access Tokenopen in new window respectively in the callback response, but Google rendered login button and One Tap prompt gives a CredentialResponseopen in new window with a JWT credential field, so if you are using a combination of these, validating your callback response on server-side can be a little tricky, this is more explained here

Some times you may not need the default button rendered by Google, you can create your own button and can make it behave like a login with Google button

This can be done in three ways

Custom Button As Slot

Create your own button component and keep it inside GoogleLogin component, default slot content of GoogleLogin component is considered as a custom login button and it will act as a login with Google button

<script setup>
const callback = (response) => {
  console.log("Handle the response", response)
}
</script>

<template>
  <GoogleLogin :callback="callback">
    <button>Login Using Google</button>
  </GoogleLogin>
</template>

💡 By default this will give Auth codeopen in new window in response, you can use the prop popup-type="TOKEN" to get Access Tokenopen in new window instead

googleAuthCodeLogin function

You can use googleAuthCodeLogin function to dynamically trigger the opening of login popup, response will have an OAuth2 authorization codeopen in new window

<script setup>
import { googleAuthCodeLogin } from "vue3-google-login"
const login = () => {
  googleAuthCodeLogin().then((response) => {
    console.log("Handle the response", response)
  })
}
</script>

<template>
  <button @click="login">Login Using Google</button>
</template>

googleTokenLogin function

Just like googleAuthCodeLogin function you can use googleTokenLogin function to trigger the opening of login popup that gives an Access Tokenopen in new window instead of an Auth code

<script setup>
import { googleTokenLogin } from "vue3-google-login"
const login = () => {
  googleTokenLogin().then((response) => {
    console.log("Handle the response", response)
  })
}
</script>

<template>
  <button @click="login">Login Using Google</button>
</template>

Here is an image showing how a custom button opens the Google login popup

Using Google SDK

If you want to directly use the API provided by Google Identity Services JavaScript SDKopen in new window without even initializing the plugin, you can use googleSdkLoaded wrapper function to do that. This will run an action in which you can use the API directly, and under the hoods it will make sure that this action is performed only after the SDK library is fully loaded.

Here is an example showing how we can use googleSdkLoaded wrapper function to create a custom login button

<script setup>
import { googleSdkLoaded } from "vue3-google-login"
const login = () => {
  googleSdkLoaded((google) => {
    google.accounts.oauth2.initCodeClient({
      client_id: '352931034399-ht1i7mqefgrbsn67a4b1nm991bvat47l.apps.googleusercontent.com',
      scope: 'email profile openid',
      callback: (response) => {
        console.log("Handle the response", response)
      }
    }).requestCode()
  })
}
</script>

<template>
  <button @click="login">Login Using Google</button>
</template>

💡 You can find the docs on how to use this SDK hereopen in new window and hereopen in new window

TypeScript

If you are using Vue 3 with TypeScript you may need to add type to the callback function triggered by GoogleLogin component, you can do this by importing CallbackTypes

⚠️ If you are trying to implement a custom button and one-tap login using GoogleLogin component alone like this, you cannot add type to the callback instead you can add any type to the callback response or the recomended way is to implement this using googleOneTap and googleAuthCodeLogin/googleTokenLogin funtions

CredentialCallback

Use CredentialCallback type for the callback of Google rendered login button using GoogleLogin component, you can also use this type for the callback from One-Tap/Automatic Login prompts

<script setup lang="ts">
import type { CallbackTypes } from "vue3-google-login";
const callback: CallbackTypes.CredentialCallback = (response) => {
  // This callback will be triggered when the user selects or login to
  // his Google account from the popup
  console.log("Credential JWT string", response.credential);
};
</script>

<template>
  <GoogleLogin :callback="callback" />
</template>

CodeResponseCallback

Use CodeResponseCallback type for the callback trigered by GoogleLogin component when a custom button is kept as slot

<script setup lang="ts">
import type { CallbackTypes } from "vue3-google-login";
const callback: CallbackTypes.CodeResponseCallback = (response) => {
  console.log("Authorisation code", response.code);
};
</script>

<template>
  <GoogleLogin :callback="callback">
    <button>Login Using Google</button>
  </GoogleLogin>
</template>

TokenResponseCallback

Use TokenResponseCallback type for the callback trigered by GoogleLogin component when a custom button is kept as slot and popup-type prop is set to TOKEN

<script setup lang="ts">
import type { CallbackTypes } from "vue3-google-login";
const callback: CallbackTypes.TokenResponseCallback = (response) => {
  console.log("Access token", response.access_token);
};
</script>

<template>
  <GoogleLogin :callback="callback" popup-type="TOKEN">
    <button>Login Using Google</button>
  </GoogleLogin>
</template>

Server-side Validation

Once the callback is triggered you need to validate the callback response using your Server-side endpoints, but this is done differently for the callback triggered by Google rendered login button/One Tap prompts and callback triggered by Custom Login Button

Google rendered login button/One Tap prompts

Callback will be triggered with a CredentialResponseopen in new window with a JWT credential string

Here is a sample Node.js code snippet for validating the JWT credential string

const { OAuth2Client } = require('google-auth-library')
const client = new OAuth2Client("YOUR_GOOGLE_CLIENT_ID")

// Call this function to validate the JWT credential sent from client-side
async function verifyCredentials(credential) {
  const ticket = await client.verifyIdToken({
    idToken: credential,
  })
  const payload = ticket.getPayload()
  return payload
}

verifyCredentials('JWT_CREDENTIAL_STRING_FROM_CLIENT_SIDE').then((userInfo) => {
  // use userInfo and do your server-side logics here
}).catch((error) => {
  // validation failed and userinfo was not obtained
})

Custom Login Button

Validating Auth Code

If you are using googleAuthCodeLogin function or google.accounts.oauth2.initCodeClientopen in new window, the response you get on successfull login contains an OAuth2 authorization codeopen in new window

Here is a sample Node.js code snippet for validating this OAuth2 authorization code from the response

const { OAuth2Client } = require('google-auth-library')
const client = new OAuth2Client(
  {
    clientId: 'YOUR_GOOGLE_CLIENT_ID',
    clientSecret: 'YOUR_GOOGLE_CLIENT_SECRET',
    redirectUri: 'YOUR_GOOGLE_REDIRECT_URI'
  }
)

// Call this function to validate OAuth2 authorization code sent from client-side
async function verifyCode(code) {
  let { tokens } = await client.getToken(code)
  client.setCredentials({ access_token: tokens.access_token })
  const userinfo = await client.request({
    url: 'https://www.googleapis.com/oauth2/v3/userinfo'
  })
  return userinfo.data
}

verifyCode('AUTHORIZATION_CODE_FROM_CLIENT_SIDE').then((userInfo) => {
  // use userInfo and do your server-side logics here
}).catch((error) => {
  // validation failed and userinfo was not obtained
})
Validating Access Token

If you are using googleTokenLogin function or google.accounts.oauth2.initTokenClientopen in new window, the response you get on successfull login contains an Access Tokenopen in new window

Here is a sample Node.js code snippet for validating this Access Token from the response

const { OAuth2Client } = require("google-auth-library")
const client = new OAuth2Client()

// Call this function to validate OAuth2 authorization code sent from client-side
async function verifyToken(token) {
  client.setCredentials({ access_token: token })
  const userinfo = await client.request({
    url: "https://www.googleapis.com/oauth2/v3/userinfo",
  });
  return userinfo.data
}

verifyToken("ACCESS_TOKEN_FROM_CLIENT_SIDE")
  .then((userInfo) => {
    console.log(userInfo)
  })
  .catch((error) => {
    console.log(error)
  })

Combination of One Tap Prompt and Custom Button

If you are using the combination of these like below, then the response caught in callback function can be different based on the user action, you can handle this by making serverside endpoints which accepts both type of responses and in callback function conditionally call these endpoints

<script setup>
const callback = (response) => {
  if(response.credential) {
    console.log("Call the endpoint which validates JWT credential string")
  } else {
    console.log("Call the endpoint which validates authorization code")
  }
}
</script>

<template>
  <GoogleLogin :callback="callback" prompt auto-login>
    <button>Add</button>
  </GoogleLogin>
</template>

Options

Plugin options and GoogleLogin component props

Options of plugin used at initializing in main.js and prop values in GoogleLogin component are similar

NameTypeDescription
clientIdStringGoogle API client ID
promptBooleanSet this to true to display the One Tap prompt

Setting this value as a prop of GoogleLogin component will be ignored if this is set as option on initializing the plugin
autoLoginBooleanSetting this value to true will make the prompt to automatically log in without any user interactions

For this to work prompt must be set to true

Setting this value as a prop of GoogleLogin component will be ignored if this is set as option on initializing the plugin
popupTypeStringType of callback response, accepts either CODE or TOKEN, this only works if a custom button is added as a slot button
callbackFunctionThe callback function which will be trigger with a response object once the login is completed
errorFunctionAn error function which will be triggered on any error encountered while showing the prompts/popups
idConfigurationObjectIdConfiguration object for initializing, see list of fields and descriptions of the IdConfiguration hereopen in new window
buttonConfigObjectConfiguration of the login button rendered by Google, see list of fields and descriptions of these configurations hereopen in new window

Function googleOneTap

googleOneTap function accepts the following options

NameTypeDescription
clientIdStringGoogle API client ID
contextStringThe title and words in the One Tap prompt, this can be signin|signup|use see hereopen in new window for more info
autoLoginBooleanSet this to true if you want the one-tap promt to automatically login
cancelOnTapOutsideBooleanControls whether to cancel the prompt if the user clicks outside of the prompt

Function googleAuthCodeLogin and googleTokenLogin

googleAuthCodeLogin and googleTokenLogin functions accepts an object with client id, this is useful if you are not planning to initialize the plugin in main.js

NameTypeDescription
clientIdStringGoogle API client ID