DEV Community

Cover image for Authentication with Google in NodeJS
Uddesh
Uddesh

Posted on • Edited on

Authentication with Google in NodeJS

While working on OAuth for a long time. I have finally understood the flow. But a few days back I had no idea how OAuth works and I was very frustrated and I need to implement it. So I just started to write some code and messing around with Gmail API. After scratching my head for the whole night I was able to login with google. So I thought I should share the process.

Now without further delay let's get started.

1) Goto google developer console.

2) Create a new project

Alt Text

3) Select the project and click credentials in the sidebar.

Alt Text

4) Now select OAuth client ID

Alt Text

5) Now Select Web Application in application type. The name could be whatever you want, in Authorized JavaScript origins add this line

http://localhost:5000
Enter fullscreen mode Exit fullscreen mode

and in Authorized redirect URIs field add this line

http://localhost:5000/auth/google/callback
Enter fullscreen mode Exit fullscreen mode

and click on create.

Alt Text

6) Download the credentials JSON file by clicking on the tiny download button.

Alt Text

Your credentials JSON file should look like this after few changes.

{
    "client": {
        "id": "put you id here",
        "secret": "put your secret key here",
        "redirect": "http://localhost:5000/auth/google/callback"
    },

    // Don't change the code below this line

    "credentials": {
        "access_token": "your access_token",
        "token_type": "Bearer",
        "expires_in": 3600,
        "refresh_token": "your refresh_token"
    }
}
Enter fullscreen mode Exit fullscreen mode

7) Now open your favorite code editor (mine is vscode) and create an index.js file and put the credential JSON file in the same folder.

8) run npm init command and just set all options to default.

9) Install express npm i express and google API package npm i googleapis

10) Rename your credential JSON file to google_key.json. Just an extra step you can name whatever you want.

11) Paste this code below in index.js file.

const { google } = require('googleapis');
const express = require('express')
const OAuth2Data = require('./google_key.json')

const app = express()

const CLIENT_ID = OAuth2Data.client.id;
const CLIENT_SECRET = OAuth2Data.client.secret;
const REDIRECT_URL = OAuth2Data.client.redirect

const oAuth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL)
var authed = false;

app.get('/', (req, res) => {
    if (!authed) {
        // Generate an OAuth URL and redirect there
        const url = oAuth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: 'https://www.googleapis.com/auth/gmail.readonly'
        });
        console.log(url)
        res.redirect(url);
    } else {
        const gmail = google.gmail({ version: 'v1', auth: oAuth2Client });
        gmail.users.labels.list({
            userId: 'me',
        }, (err, res) => {
            if (err) return console.log('The API returned an error: ' + err);
            const labels = res.data.labels;
            if (labels.length) {
                console.log('Labels:');
                labels.forEach((label) => {
                    console.log(`- ${label.name}`);
                });
            } else {
                console.log('No labels found.');
            }
        });
        res.send('Logged in')
    }
})

app.get('/auth/google/callback', function (req, res) {
    const code = req.query.code
    if (code) {
        // Get an access token based on our OAuth code
        oAuth2Client.getToken(code, function (err, tokens) {
            if (err) {
                console.log('Error authenticating')
                console.log(err);
            } else {
                console.log('Successfully authenticated');
                oAuth2Client.setCredentials(tokens);
                authed = true;
                res.redirect('/')
            }
        });
    }
});

const port = process.env.port || 5000
app.listen(port, () => console.log(`Server running at ${port}`));
Enter fullscreen mode Exit fullscreen mode

12) Run index.js

Google will ask you to sign in and allow access. Then you will be signed in and as we are fetching only Gmail labels in this API. You will get output in the console like this.

Alt Text

Note:- If you get some error due to not having https enabled don't panic. Click on See more button and allow google to access your profile manually.

Click on show advance and then click on Go to 'your app name'(unsafe) and allow it.

Alt Text

I hope this will help. I'll be back with another one, until then Bye.

Bye Gif

Top comments (11)

Collapse
 
abinhho profile image
abinhho

I got this error (Mar 2020)

400. That’s an error.

Error: invalid_request
Custom scheme URIs are not allowed for 'WEB' client type.

Request Details
response_type=code
redirect_uri=testauth.com:3000
scope=email profile
client_id=xxx-rm7s51vmr320brk5b5mrhopgma0e65o9.apps.googleusercontent.com
Collapse
 
yeoupooh profile image
Thomas Jinwoo Min

Thank you for the helpful article.

I found some trivial errors in getting value from OAuth2Data with latest google_key.json.
Below is the fix.

const CLIENT_ID = OAuth2Data.web.client_id;
const CLIENT_SECRET = OAuth2Data.web.client_secret;
const REDIRECT_URL = OAuth2Data.web.redirect_uris;

Collapse
 
uddeshjain profile image
Uddesh

I glad it helped you. An error could be due to the change in the structure of credentials but I'll take look on it.

Collapse
 
ananayarora profile image
Ananay Arora

Thomas, thanks for the fix! This fix is indeed correct and is necessary for the app to function.

Collapse
 
rizwanalam91 profile image
Rizwan Alam

thanks uddesh,,it helped me,,,thanks man for this...
best part is that it is in very very simple language.
i am developing an app in flutter and backend with node js,,
now could u plz guide me that how i can integrate this with my app.
it is running fine in terminal and browser,,but how i can connect this functionality with my app

Collapse
 
rpatelmt profile image
Ritesh Patel

Hiii.... Uddesh ... This is very useful to me.... and it is successfully working for me... But now i want to get my gmail User Name (first name, last name) and email and profile pic...I have used this "gmail.users.getProfile()"...But this gives me only email addeess and other info..But it does not return my gmail account First name, last Name, profile pic url, i don't know how to do it ... do you have any idea ?

Please help me ..

Thank you

Collapse
 
vaibh36 profile image
vaibh36

I am able to get the data for the fitness api My problem is that i am hitting the same api using an android phone for an app based on react-native.
I am not able to do res.redirect(url) on the mobile device. Please suggest.

Appreciate your support!

Collapse
 
dreambit profile image
dreambit • Edited

It is better not to use google lib, and do it by hands by using google rest api.
No magic and no black box.

Collapse
 
mochramdan profile image
Moh Ramdan

Error authenticating
GaxiosError: invalid_request
at Gaxios. (D:\ramdan\my-project\cms-app\node_modules\gaxios\build\src\gaxios.js:73:27)

sorry, I got this error message, what does mean?

Collapse
 
vinothsm92 profile image
Vinoth • Edited

Hi uddesh,
It's is very easy to understand your example.
But I have few doubts in this.

how to get the logged in user's mail id.

Can you help me in this.

Collapse
 
sauravexodus profile image
Sourav Chandra

Very nice brother!