Authenticate user with passport through LinkedIn login

你离开我真会死。 提交于 2021-02-08 03:54:24

问题


I have built a login system in Passport and works quite well. Now, I want to integrate LinkedIn login in my system. I already have clientID, clientSecret etc. needed to login. This is the code that is called when the LinkedIn login button is pressed.

passport.use('linkedin', new OAuth2Strategy({
    authorizationURL: 'https://www.linkedin.com/uas/oauth2/authorization',
    tokenURL: 'https://www.linkedin.com/uas/oauth2/accessToken',
    clientID: clientid,
    clientSecret: clientsecret,
    callbackURL: '/linkedinLogin/linkedinCallbackUrlLogin',
    passReqToCallback: true
},
function(req,accessToken, refreshToken, profile, done) {
    console.log('authenticated');
    console.log(accessToken);
    req.session.code = accessToken;
    process.nextTick(function () {
        done(null, {
            code : req.code
        });
    });
}));

Both the console.log() calls in the callback function are successfully fired, this means I am successfully logged in through LinkedIn and I receive my access token. The part where I connect with LinkedIn is thus correct, what I am missing is the part where I actually log in the user. As you can see, the callbackURL points to /linkedinLogin/linkedinCallbackUrlLogin. This is what I do in that route:

app.get('/linkedinLogin/linkedinCallbackUrlLogin', passport.authenticate('linkedin', {
    session: false,
    successRedirect:'/linkedinLogin/success',
    failureRedirect:'/linkedinLogin/fail'
}));

I just specify a successRedirect and a failureRedirect. Note that if I put session : true I receive as an error Failed to serialize user into session, so for now I keep it to false.

The successRedirect is successfully called. In that route I call a GET request to LinkedIn to access some data about the user. I want to store this data in my DB and remember the user that logged in. This is how I do it:

https.get(
    {
    host: 'api.linkedin.com' ,
    path: '/v1/people/~?format=json' ,
    port:443 ,
    headers : {'Authorization': ' Bearer ' + req.session.code}
    },
    function(myres) {
        myres.on("data", function(chunk) {
            var linkedinJsonResult = JSON.parse(chunk);
            User.findOne({linkedinLogin : linkedinJsonResult.id}, function(err, userSearchResult){
                if(err) {
                    throw err;
                }

                //user found, login
                if(userSearchResult){
                    console.log(userSearchResult);
                }
                else {
                    //create user
                    var newUser = new User(
                        {
                            url : linkedinJsonResult.siteStandardProfileRequest.url,
                            name : linkedinJsonResult.firstName + " " + linkedinJsonResult.lastName,
                            linkedinLogin : linkedinJsonResult.id,
                            regDate : new Date()
                        }
                    );

                    //save user
                    newUser.save(function(err, user){
                        if(err){
                            throw err;
                        }

                        //login
                        console.log(user);
                    });
                }

            });
    });
    }
);

Let me explain the code there. After getting the data of the user I check the field "id" that is received. If this id matches one of my users' linkedinLogin field stored into the DB, I consider it already registered (the user has been found in the DB), thus I have to log him/her in. Otherwise I just create a new user using the data received from the GET request.

My question is, in both the cases - the user is found in my DB, or the user has to be created - how can I set req.user to be my user whenever it interacts with my website? Is it sufficient to just do req.user = userSearchResult (if the user is found, inside the if statement) or req.user = user (if the user has been created, inside the newUser.save() callback), or should I call some passport functions that will set it for me?

All the other passport functions related to the registration and login of users without using LinkedIn login are working fine. I am just worried about making this LinkedIn login work with passport.

Thank you.


回答1:


passport.js will automatically set the req.user object to the object you will pass as the second argument to the done function of the strategy callback.

This means that you should do something like this:

function(req,accessToken, refreshToken, profile, done) {
    console.log('authenticated');
    console.log(accessToken);
    req.session.code = accessToken;
    process.nextTick(function () {
        // retrieve your user here
        getOrCreateUser(profile, function(err, user){
            if(err) return done(err);
            done(null, user);
        })

    });
}));

I hope this helps.



来源:https://stackoverflow.com/questions/34738225/authenticate-user-with-passport-through-linkedin-login

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!