How to correctly authenticate through Passport with Google access tokens using the OAuth 2.0 API?

359 views Asked by At

I'm trying to use Passport-Google-Token strategy for user authentication similar with Facebook strategy, that works just fine, but for some reason Google authentication, even though all parameters seems to be configured correctly don't return any information and stuck on it. Any advice would be highy appreciated.

const GoogleTokenStrategy = require('passport-google-token').Strategy;

passport.use('googleToken', new GoogleTokenStrategy(
    {
        clientID: process.env.GOOGLE_CLIENT_ID,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET
    }, function(accessToken, refreshToken, profile, done) {

        console.log('profile google: ', profile);
        const email = profile.email;
        const name = profile.name;
        const firstname = profile.given_name;
        const lastname = profile.family_name;

        User.findOne({ email: email }, function (err, user) {
            if (err) { return done(err); }
            // Return if user not found in database
            if (!user) {
                const newUser = new User({
                    _id: new mongoose.Types.ObjectId(),
                    name: name,
                    firstname: firstname,
                    lastname: lastname,
                    email: email
                });

                newUser.save()
                    .then(result => {
                        return done(null, newUser);
                    })
                    .catch(err => {
                        console.log(err);
                        return done(null, false, {
                            statusCode: 500,
                            message: 'Server error',
                            error: err.message
                        });
                    });
            }
            return done(null, user);
        }).catch(err => {
            console.log(err);
            return done(null, false, {
                statusCode: 500,
                message: 'Server error',
                error: err.message
            });
        });
    }
));

exports.googleLogin = (req, res, next) => {
console.log('started google login');
return passport.authenticate(['googleToken'], function(error, user, info) {
    var token;

    if (err) {
        return res.status(404).json({
            statusCode: 404,
            message: 'Auth failed',
            error: err
        });
    }

    if (info) {
        return res.status(401).json({
            statusCode: 401,
            message: 'Auth failed',
            error: info[0]
        });
    }

    // If a user is found
    if (user) {
        token = user.generateJwt();
        return res.status(200).json({
                id: user._id,
                name: user.name,
                email: user.email,
                token: token
        });
    } else {
        const error = new Error("User not found");
        return res.status(403).json({
            statusCode: 403,
            message: 'Auth failed',
            error: error
        });
    }
})}; 

router.post('/googleLogin', controller.googleLogin);
1

There are 1 answers

0
Max Niagolov On BEST ANSWER

I just ended up using Google API Client Library instead of a Passport strategy:

const {OAuth2Client} = require('google-auth-library');
    const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);

        const token = req.body.idtoken;
        async function verify() {
            const ticket = await client.verifyIdToken({
                idToken: token,
                audience: process.env.GOOGLE_APP_CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
                // Or, if multiple clients access the backend:
                //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
            });
            const payload = ticket.getPayload();
            const userid = payload['sub'];
            console.log('payload: ', payload)
            // If request specified a G Suite domain:
            //const domain = payload['hd'];
        }

        verify().catch(console.error);