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

1

7

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.

Strophanthus answered 26/1, 2018 at 17:50 Comment(8)
Have you tried this from somewhere else than localhost ? CORS headers are sometimes not set on localhost (in Chrome for instance you need an extension to make it work).Runoff
@Runoff is correct about the CORS error. You can try to use a different browser but Chrome by default doesn't allow localhost to localhost access. One possible way of correcting that is to enable cors middleware on the node server.Methodical
Thanks, KeatsPeeks RickyM But I want the general solution and many people use Chrome BrowserStrophanthus
@Batman You don't understand, we're talking about localhost only, "people" won't use localhost to use your website. Install it somewhere and try again. -Runoff
Ohh okay let me check on the real server and checkStrophanthus
I have the same issue in all browsers. @Batman how did you solve this issue?Lottery
Finally I ended up and not using passport-facebook but you can solve the issue by CORS using this addon in MozillaStrophanthus
@Batman there are CORS plugins for Chrome as well, like this one: chrome.google.com/webstore/detail/allow-control-allow-origi/…Calumnious
C
1

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");
                                }
                            }
                        });
                    }
                });
            }
        });
    });
};
Cussedness answered 15/10, 2019 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.