0

After spending close to a week trying to implement passport strategy for google token unsuccessfully, I decided write it myself using the Nodejs client library for Google API. I'm passing the accesstoken from angularjs in a $http request and want to return the logged in user to the call after authenticating on the server side. I'm having trouble in passing the signed in user to the req object so I can pass it to the next middleware. Any help will be greatly appreciated.

**express code**

router

var gCtrl = require('./googleController.js');
app.post('/auth/google/accesstoken',


      function (req, res) {
         console.log('Im in the google auth middleware');

     //below line is not returning the gUser so I can pass it to the next middleware
        var gUser=gCtrl(req.token);

        res.send(gUser); 
}, 
 function(req,res){
    //do something with authenticated user
    }
);

gCtrl Module that makes the Google API call

var ubCust = require('../models/ubCust.js');
var bodyParser = require('body-parser');

var google=require('googleapis');
var plus = google.plus('v1');
var OAuth2 = google.auth.OAuth2;
var oauth2client = new OAuth2('1094664898379-8u0muh9eme8nnvp95dafuc3rvigu4j9u.apps.googleusercontent.com','KQ_vNDaZzTvXDdsfgp5jqeZW','http://localhost:3000/auth/google/callback');


module.exports = function(acc_token){


        //console.log(acc_token);
         oauth2client.setCredentials({
            access_token : acc_token
        //refresh_token: token.refresh_token
        });

        plus.people.get({
            userId:'me',
            auth:oauth2client
        },function(err,response){
            if (err) 
                throw err;
            //console.log('google user',response);
            return response;
        });

  };

1 Answers1

3

You are missing an understanding of how one returns values from an asynchronous operation. Where you have return response in your gCtrl module is just returning the value internally to whatever the async operation is inside of plus.people.get(). That will not return the value from your module.exports function. That function has long since returned.

You can read about the general concept of returning values from an async operation here: How do I return the response from an asynchronous call?. You will need to use either a callback function or a promise to communicate back an asynchronous value. You cannot return it directly.

Now, in your specific case, you could use your gCtrl module as Express middleware where you set the intermediate token value into the req object in your middleware handler and then use next() to communicate that it's now time to call your main handler for the request. You can do that like this:

// gtrl - Express middleware handler
// the purpose of this middleware is to process req.token 
//    and set req.tokenResponse for further processing
//    in the next step of the middleware/request handler processing
module.exports = function(req, res, next) {
     oauth2client.setCredentials({
        access_token : req.token
    //refresh_token: token.refresh_token
    });

    plus.people.get({
        userId:'me',
        auth:oauth2client
    }, function(err,response){
        if (err) {
            // communicate back error in some fashion, may want to return a 5xx response for an internal error
            next(err);
        } else {
            // set value into req object for later consumption
            req.tokenResponse = response;
            // call next handler in the chain
            next();
        }
    });
  };

// router
var gCtrl = require('./googleController.js');

// use gCtrl middleware to do async processing on req.token
app.post('/auth/google/accesstoken',  gCtrl, function(req, res) {
    // req.tokenResponse is set here by the gCtrl middleware
    // do something with authenticated user

    // send some sort of response here
    res.send(...);
});

Note: to make this work, we have to specifically make the gCtrl exported function match the function signature of express middleware and it retrieves the token directly from the req object. You could make the gCtrl module independent of Express and just make it an async function that uses a callback or a promise to communicate back when it has it's data and then code the express handler to call that function and use that async return value appropriately. In my code above, I chose to use the already built middleware architecture for handling the async response.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979