Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Facebook Graph API with passport-facebook in NodeJS with Express

Before Asking this Question I have referred the below but didn't help me

  1. Passport.js & Facebook Graph API
  2. Retrieving photo from Facebook using passport-facebook
  3. https://www.hitchhq.com/facebook-graph-api/docs/facebook-authentication
  4. http://tech.bigstylist.com/index.php/2017/08/12/search-facebook-graph-api-nodejs/
  5. How to use Facebook Graph API after authenticating with Passport.js facebook strategy? enter link description here

And Some posts say to use passport-facebook-token But I don't want to use as I want to extend the existing functionality of my application with passport-facebook only

Problem Statement

Currently, I am using passport-facebook for authentication which works perfectly and Now I want to extend the functionality to use Facebook Graph API to get the photos of the users who log in to my application

So use the Facebook Graph API to get the user photos I have to make below call using request module in Node JS, The body part will return me the expected result

var request = require("request");

var options = {
    method: 'GET',
    url: 'https://graph.facebook.com/me/photos/',
    qs: {
        access_token: 'EBBCEdEose0cBADwb5mOEGISFzPwrsUCrXwRWhO87aXB9KsVJlgSLc19IdX9D9AKU7OD5SdFOqPXW3eLm8J3HltZC14VexdMsEDW35LDWASdVDNGp5brFERBETsIvxXJIFXo7QSum5apHXeRyQk7c2PQljmf5WHObZAwXVzYjqPd4lziKTUK48Wfrw5HPwZD'
    },
    headers: {
        'content-type': 'application/json'
    }
};

request(options, function (error, response, body) {
    if (error) throw new Error(error);

    console.log(body);
});

But now I wanted to create my custom express GET API when I call that I use should be getting the above body response,

like GET : /graph/photos

app.get('/graph/photos', function (req, res) {
    res.send(body)//Here I wanted to get the same response as of the request module above
});

But I have the below challenges

  1. Getting the access_token from the passport-facebook and pass that to the request module
  2. If the user is not authenticated thrown an error in the API response

But I could able to proceed somewhat with below approach, I have followed the tutorial from

https://github.com/scotch-io/easy-node-authentication/tree/linking

app.get('/graph/photos', isLoggedIn, function (req, res) {
    var hsResponse = request({
        url: 'https://graph.facebook.com/me/photos',
        method: 'GET',
        qs: {
            "access_token": req.user.facebook.token
        },
    }, function (error, response, body) {
        res.setHeader('Content-Type', 'application/json');
        res.send(body);
    });
});

But the problem I am facing is every time call the API /graph/photos/, It will try to redirect to check whether the user is logged in hence I won't be directly able to use in Angular Service and getting below error

Error

Failed to load http://localhost:3000/graph/photos: Redirect from 'http://someurl' to 'http://someurl' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

like image 266
Mahesh G Avatar asked Jan 26 '18 17:01

Mahesh G


1 Answers

try this... I wrote the function for my project,you just customize....

// facebook login
exports.facebookLogin = function(req, res) {
    var fields = config.loginFaceBook.fbFields;
    var accessTokenUrl = config.loginFaceBook.fbAccessTokenUrl;
    var graphApiUrl = config.loginFaceBook.fbGraphApiUrl + fields.join(',');
    var params = {
        code: req.body.code,
        client_id: req.body.clientId,
        client_secret: config.loginFaceBook.fbClientSecret,
        redirect_uri: req.body.redirectUri
    };

    // Step 1. Exchange authorization code for access token.
    request.get({
        url: accessTokenUrl,
        qs: params,
        json: true
    }, function(err, response, accessToken) {
        console.log('Exchange authorization code err::', err);
        console.log('Exchange authorization code accessToken::', accessToken);
        if (response.statusCode !== 200) {
            return res.status(500).send({
                message: accessToken.error.message
            });
        }

        // Step 2. Retrieve profile information about the current user.
        request.get({
            url: graphApiUrl,
            qs: {
                access_token: accessToken.access_token,
                fields: fields.join(',')
            },
            json: true
        }, function(err, response, profile) {
            console.log('Retrieve profile information err::', err);
            console.log('Retrieve profile information::', profile);
            if (response.statusCode !== 200) {
                return res.status(500).send({
                    message: profile.error.message
                });
            }
            if (req.header('Authorization')) {
                console.log('req header Authorization', req.header('Authorization'));
            } else {
                var socialEmail;
                if (profile.email) {
                    socialEmail = profile.email;
                } else {
                    socialEmail = profile.id + '@facebook.com';
                }

                // Step 3. Create a new user account or return an existing one.
                UserModel.findOne({
                    email: socialEmail
                }, function(err, existingUser) {
                    if (existingUser) {
                        AppClientModel.findOne({
                            _id: config.auth.clientId
                        }, function(err, client) {
                            if (!err) {
                                var refreshToken = generateToken(existingUser, client, config.secrets.refreshToken);
                                var rspTokens = {};
                                rspTokens.access_token = generateToken(existingUser, client, config.secrets.accessToken, config.token.expiresInMinutes);
                                var encryptedRefToken = cryptography.encrypt(refreshToken);
                                var token = {
                                    clientId: client._id,
                                    refreshToken: refreshToken
                                };

                                UserModel.update({
                                    _id: existingUser._id
                                }, {
                                        $push: {
                                            'tokens': token
                                        }
                                    }, function(err, numAffected) {
                                        if (err) {
                                            console.log(err);
                                            sendRsp(res, 400, err);
                                        }
                                        res.cookie("staffing_refresh_token", encryptedRefToken);
                                        sendRsp(res, 200, 'Success', rspTokens);
                                    });
                            }
                        });
                    }
                    if (!existingUser) {
                        var userName = profile.first_name + ' ' + profile.last_name;
                        var newUser = new UserModel({
                            name: userName,
                            img_url: 'https://graph.facebook.com/' + profile.id + '/picture?type=large',
                            provider: 2, //2: 'FB'
                            fb_id: profile.id,
                            email_verified_token_generated: Date.now()
                        });
                        log.info("newUser", newUser);
                        newUser.save(function(err, user) {
                            if (!err) {
                                var refreshToken = generateToken(user, client, config.secrets.refreshToken);
                                var rspTokens = {};
                                rspTokens.access_token = generateToken(user, client, config.secrets.accessToken, config.token.expiresInMinutes);
                                var encryptedRefToken = cryptography.encrypt(refreshToken);

                                var token = {
                                    clientId: client._id,
                                    refreshToken: refreshToken
                                };

                                UserModel.update({
                                    _id: user._id
                                }, {
                                        $push: {
                                            'tokens': token
                                        }
                                    }, function(err, numAffected) {
                                        if (err) {
                                            console.log(err);
                                            sendRsp(res, 400, err);
                                        }
                                        res.cookie("staffing_refresh_token", encryptedRefToken);
                                        sendRsp(res, 200, 'Success', rspTokens);
                                    });
                            } else {
                                if (err.code == 11000) {
                                    return sendRsp(res, 409, "User already exists");
                                } else {
                                    return sendRsp(res, 500, "User create error");
                                }
                            }
                        });
                    }
                });
            }
        });
    });
};
like image 70
vicky Avatar answered Nov 14 '22 14:11

vicky