Integrate Google OAuth Client ID in Vue 3: Step-by-Step Guide for Secure Authentication

In this blog, we will build a project on Google OAuth integration using Vue.js 3. I will share the detailed process of how I integrated this powerful feature into a Vue.js 3 project and discuss the challenges I faced along the way. Let’s get started!
Create a Vue Project
First, create a Vue project on your local system with the following command. Open your terminal and type:
vue create <project-name>
This command will create a new Vue project on your local system.
Configure Google OAuth
Next, go to the Google Cloud Console and log in using your Google account. After completing the login process, navigate to the OAuth consent screen in the left menu. There are four steps in this section:
- Set the application information, including the app name, user support email, application logo, and app domain.
- For the app domain, use the URL:
http://localhost:8080
Then, add the developer email ID and click “Save and Continue” for all the remaining steps.

Once done, go to the “Credentials” section. Click “Create Credentials” at the top, then select “OAuth Client ID.” Choose the application type “Web application” and add the Authorized JavaScript origins and Authorized redirect URLs as shown in the image below.

Copy the Client ID
Once you have completed the process, copy the Client ID. This Client ID is crucial for the integration and will be used extensively in your project.
Project Structure
Here is your project structure:
my-vue-app/
├── public/
│ ├── index.html
│ └── …
├── src/
│ ├── assets/
│ ├── components/
│ │ ├── GoogleAuth.vue
│ ├── views/
│ │ ├── Home.vue
│ ├── App.vue
│ ├── main.js
│ ├── router.js
├── server/
│ ├── index.js
│ ├── package.json
│ └── …
├── .gitignore
├── package.json
├── README.md
└── …
Required Libraries for This Project
Ensure that all the necessary libraries are properly installed. You will need:
google-auth-library
express
cors
crypto
Install them using npm or yarn to avoid any issues during development. Here’s how you can install them with npm:
npm install google-auth-library express cors crypto
Or with yarn:
yarn add google-auth-library express cors crypto
Server Setup
Create the server in server/index.js
:
const express = require(‘express’);
const cors = require(‘cors’);
const session = require(‘express-session’);
const { OAuth2Client } = require(‘google-auth-library’);
const client = new OAuth2Client(‘GOOGLE-CLIENTid.apps.googleusercontent.com’);
const crypto = require(‘crypto’);
const app = express();
// Generate a secure secret key for session encryption
const secret = crypto.randomBytes(64).toString(‘hex’);
// Configure CORS to allow requests from the frontend
app.use(cors({
origin: ‘http://localhost:8080',
credentials: true,
}));
// Middleware to parse JSON requests
app.use(express.json());
// Configure session middleware
app.use(session({
secret: secret, // Use the generated secret key
resave: false, // Don’t save the session if it wasn’t modified
saveUninitialized: true, // Save uninitialized sessions
cookie: {
maxAge: 300000, // Session expires after 5 minutes (300,000 ms)
},
}));
// Endpoint to verify the Google ID token
app.post(‘/verify-token’, async (req, res) => {
const { token } = req.body;
try {
// Verify the ID token using the Google OAuth2 client
const ticket = await client.verifyIdToken({
idToken: token,
audience: ‘GOOGLE-CLIENTid.apps.googleusercontent.com’,
});
const payload = ticket.getPayload();
// Store user information in the session
req.session.user = payload;
req.session.cookie.expires = new Date(Date.now() + 300000);
req.session.cookie.maxAge = 300000;
res.json({ verified: true, payload });
} catch (error) {
console.error(‘Error verifying token:’, error);
res.status(401).json({ verified: false });
}
});
// Endpoint to handle logout and destroy the session
app.post(‘/logout’, (req, res) => {
req.session.destroy(err => {
if (err) {
console.error(“Error destroying session:”, err);
res.status(500).send(‘Error signing out’);
} else {
res.clearCookie(‘connect.sid’); // Clear the session cookie
res.send({ success: true });
}
});
});
// Endpoint to check session status
app.get(‘/session-info’, (req, res) => {
if (req.session.user) {
res.json({ sessionActive: true, user: req.session.user });
} else {
res.json({ sessionActive: false });
}
});
// Start the server on port 3000
app.listen(3000, () => {
console.log(‘Server is running on http://localhost:3000');
});
Vue Component
Create the Vue component in src/components/GoogleAuth.vue
:
<template>
<div id=”app”>
<! — Show “Sign in with Google” button if the user is not signed in →
<button v-if=”!isSignedIn” @click=”handleAuthClick”>Sign in with Google</button>
<! — Show “Sign out” button if the user is signed in →
<button v-else @click=”signOut”>Sign out</button>
<! — Display user information if the user is signed in →
<div v-if=”isSignedIn”>
<h3>User Information</h3>
<p><strong>Name:</strong> {{ userInfo.name }}</p>
<p><strong>Email:</strong> {{ userInfo.email }}</p>
<img :src=”userInfo.picture” alt=”User Picture” />
</div>
</div>
</template>
<script>
export default {
name: ‘App’,
data() {
return {
isSignedIn: false, // Track if the user is signed in
userInfo: null, // Store user information
};
},
created() {
this.checkSession(); // Check session status when component is created
setInterval(this.checkSession, 60000); // Check session status every minute
},
methods: {
handleAuthClick() {
// Initialize Google Sign-In if the Google API is loaded
if (window.google) {
window.google.accounts.id.initialize({
client_id: ‘GOOGLE-CLIENTid.apps.googleusercontent.com’, // Google Client ID
callback: this.handleCredentialResponse, // Callback function after sign-in
auto_select: false, // Disable auto-select for extra security
});
window.google.accounts.id.prompt(); // Display the One Tap prompt
} else {
console.error(“Google API script not loaded.”);
}
},
async handleCredentialResponse(response) {
try {
console.log(‘Encoded JWT ID token: ‘ + response.credential);
const user = this.parseJwt(response.credential); // Parse the JWT to get user info
// Verify the token on the server side
const verifiedUser = await this.verifyTokenOnServer(response.credential);
if (verifiedUser) {
this.isSignedIn = true;
this.userInfo = user; // Store user info if verification is successful
} else {
throw new Error(‘Token verification failed.’);
}
} catch (error) {
console.error(‘Error during credential response handling:’, error);
}
},
async signOut() {
try {
// Call the server to destroy the session
await fetch(‘http://localhost:3000/logout’, {
method: ‘POST’,
credentials: ‘include’,
});
this.isSignedIn = false;
this.userInfo = null; // Clear user info after sign-out
console.log(‘User signed out.’);
} catch (error) {
console.error(‘Error signing out:’, error);
}
},
async verifyTokenOnServer(token) {
try {
// Send the token to the server for verification
const response = await fetch(‘http://localhost:3000/verify-token’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
credentials: ‘include’,
body: JSON.stringify({ token }),
});
if (response.ok) {
const data = await response.json();
return data.verified; // Return verification status
} else {
console.error(‘Token verification failed:’, response.statusText);
return false;
}
} catch (error) {
console.error(‘Error during token verification:’, error);
return false;
}
},
async checkSession() {
try {
// Check the session status on the server
const response = await fetch(‘http://localhost:3000/session-info’, {
method: ‘GET’,
credentials: ‘include’,
});
if (response.ok) {
const data = await response.json();
if (data.sessionActive) {
this.isSignedIn = true;
this.userInfo = data.user; // Update user info if session is active
} else {
this.isSignedIn = false;
this.userInfo = null; // Clear user info if session is inactive
}
} else {
console.error(‘Failed to check session:’, response.statusText);
}
} catch (error) {
console.error(‘Error checking session:’, error);
}
},
parseJwt(token) {
// Decode the JWT token to get the payload
const base64Url = token.split(‘.’)[1];
const base64 = base64Url.replace(/-/g, ‘+’).replace(/_/g, ‘/’);
const jsonPayload = decodeURIComponent(atob(base64).split(‘’).map(function(c) {
return ‘%’ + (‘00’ + c.charCodeAt(0).toString(16)).slice(-2);
}).join(‘’));
return JSON.parse(jsonPayload); // Parse and return the JSON payload
},
},
};
</script>
Main App Setup
Update src/App.vue
:
<template>
<HelloWorld msg=”Welcome to Login Page”/>
<LoginPage />
</template>
<script>
import HelloWorld from ‘./components/HelloWorld.vue’
import LoginPage from “./components/Login.vue”
export default {
name: ‘App’,
components: {
HelloWorld,
LoginPage
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
img{
border-radius: 10px;
}
</style>
Running the Application
Place the Google Client ID properly and run the application using:
npm run serve
Start the server:
node server/index.js
Now, you have successfully integrated Google OAuth into your Vue.js 3 project. Enjoy secure authentication with Google!
Feedback
We hope you found this guide helpful in integrating Google OAuth with Vue.js 3. Your feedback is valuable to us, so please share your thoughts and experiences in the comments section below. If you encountered any issues or have suggestions for improvement, let us know! Your input will help us enhance the quality of our tutorials and better serve the developer community. Thank you for reading!
Share on LinkedIn
If you enjoyed this tutorial, please share it on LinkedIn to help others learn and improve their Vue.js skills. Together, we can build a stronger developer community!