DEV Community

Arpan Kc
Arpan Kc

Posted on • Updated on

OAuth 2.0 with Google API in Node.js

With all the asyncs and the chainings and all the other JS shamaladingdongs , doing even simple tasks in Javascript can feel overwhelming, at least for a beginner like me.

To preface, I'm currently working on my own application which is a simple Match betting tracker to keep track of my bets, and decided to add in OAuth authentication in the app. Because why not.

The first thing I did was set up an account in Google console, and got me some shiny new credentials (client ID and client Secret) for OAuth 2.0.

I had trouble getting my head around the authentication flow with all the tokens and secrets and all that. But digging deep, it was quite simple actually and started to appreciate how google makes the process so simple and dare I say, elegant.

The first thing I did was get the google api:

  npm install googleapis

In the actual program:
initialized the api library and setup googleConfigs.


const { google } = require('googleapis');
const oauth2 = google.oauth2('v2');

const Oauth2Client = new google.auth.OAuth2(
    process.env.GOOGLE_CLIENT_ID,
    process.env.GOOGLE_CLIENT_SECRET,
    process.env.GOOGLE_REDIRECT, // this must match your google api settings
);


So basically all I had to do was these 3 things:

  1. get a Redirect url for the clients

  2. The url also contains a code which then I use to get a token ( if the user signs in to their google account that is)

  3. And finally I use the token to get the user details

Step 1:

function getConnectionUrl() {
    return Oauth2Client.generateAuthUrl({
        access_type: 'offline',
        prompt: 'consent',
        scope: defaultScope
    });
}

//Call this function somewhere in the program to get URL:
//const url = getConnectionUrl();

Step 2 and 3:

function getUserDetails(code) {
    return Oauth2Client.getToken(code)   //use code to get the token
        .then(({ tokens }) => {
            Oauth2Client.setCredentials(tokens);     //add token to the Oauth credentials
        })
        .then(() => {
            return oauth2.userinfo.get({ auth: Oauth2Client });  // get userinfo with the newly updated credentials
        })
}

And so in the main program , I got a connection url using getConnectionUrl() which then gave me the code in the url which I passed on to getUserDetails() to get the user details.

So this is how I got OAuth authentication working in my application.

Thanks for reading. Would appreciate feedbacks.

If you want to check out my repo, here's the link :

Please star it, if you like it.

P.S. Please follow me on twitter, I'd really appreciate it. @Nipeshkc

*UPDATE*

Using async-await steps 2 and 3 can be reduced to ::

 function async getUserDetails(code) {
   const {tokens} = await Oauth2Client.getToken(code);
   Oauth2Client.setCredentials(tokens);
   const usr_info = await oauth2.userinfo.get({auth: Oauth2Client});
   return usr_info;
 } 

This looks cleaner and async await seems to be more intuitive to use.

Oldest comments (9)

Collapse
 
epranka profile image
Edvinas Pranka

Nice and simple. Just one advice: Why are you not using the ES6 async/await? Your "Step 2 and 3" can look like:

 function async getUserDetails(code) {
   const {tokens} = await Oauth2Client.getToken(code);
   await Oauth2Client.setCredentials(tokens);
   return oauth2.userinfo.get({auth: Oauth2Client});
 } 
Enter fullscreen mode Exit fullscreen mode

Good luck!

Collapse
 
nipeshkc7 profile image
Arpan Kc

Thanks for your feedback. Honestly did not know how async-await worked, but did a bit of research and I edited the code to incorporate them.

 function async getUserDetails(code) {
   const {tokens} = await Oauth2Client.getToken(code);
   Oauth2Client.setCredentials(tokens);
   const usr_info = await oauth2.userinfo.get({auth: Oauth2Client});
   return usr_info;
 } 

A minor change from your suggestion, as .setCredentials() isn't async to my knowledge and I think userinfo.get() is. Feel free to correct me if I'm wrong.

Again thanks for your suggestion and will update the post accordingly.

Collapse
 
epranka profile image
Edvinas Pranka

I think it's ok. Async/Await is an amazing ES6 feature, keep going with that. You might forget about the callback hell.

And one more thing. Await can be used with the sync functions. It just does nothing if you make a mistake. E.g.


const asyncMethod = () => {
   return new Promise(resolve => {
      setTimeout(() => resolve('Hello'), 1000);
   });
}

const syncMethod = () => {
   return 'World';
}

function async greeting = () => {
   const hello = await asyncMethod();
   // below await is not needed, but it works too
   const world = await syncMethod(); 
   console.log(hello, world); // logs Hello World
}

Of course, you don't have to put await anywhere, but if you don't know if the function is async or sync just put it and you will be right.

Good luck!

Collapse
 
eddie023 profile image
Manish Chaulagain

Hi arpan, how you doing?
Some tips to start off your full stack career in the right way

  1. Try learning typescript this will help you a lot for big js projects.
  2. Use arrow functions and other es6 syntax.
  3. Add linter and prettier to format your code. This is one suggestion I would like to emphasis on to learn from the beginning. You will thank me later. See airBnB style guide.
  4. Also try to see how to structure js projects. Learn to modularize relevant suff into one place.

Great to see that you are sharing your coding journey! Best of luck. :)

Collapse
 
bcdbuddy profile image
Babacar Cisse DIA

hey man you did well on this. You spare me time by writing this article, I was planning on integrating oauth too. Thanks

Collapse
 
rinah profile image
rinahs

what is this code you use in getUserDetails

Collapse
 
nipeshkc7 profile image
Arpan Kc

So basically, what it does is,

  1. it takes out the 'token' from the code received
  2. adds the token to the Oauth2Client credentials (which is used to fetch the user data)
  3. Fetches the user's data from Google.
Collapse
 
milenarosazoly profile image
Milena Boselli Rosa

Awesome job. Thanks!

Collapse
 
saurabhd12345678 profile image
saurabhd12345678

are you passing the url in code paramater if not then what it is can you please enlighten ,Stucked at that point