通过LinkedIn登录使用护照对用户进行身份验证

问题描述:

我已经在Passport中建立了一个登录系统,并且运行良好.现在,我想将LinkedIn登录集成到我的系统中.我已经有需要登录的 clientID clientSecret 等.这是按下LinkedIn登录按钮时所调用的代码.

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
        });
    });
}));

回调函数中的 console.log()调用均被成功触发,这意味着我已通过LinkedIn成功登录,并且收到了访问令牌.因此,我与LinkedIn建立联系的部分是正确的,而我真正登录用户的部分是我所缺少的.如您所见, callbackURL 指向/linkedinLogin/linkedinCallbackUrlLogin .这是我在那条路线上所做的:

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'
}));

我只指定一个 successRedirect 和一个 failureRedirect .请注意,如果我将 session:true 放入,则会收到错误消息无法将用户序列化为会话,因此现在我将其设置为false.

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.

成功调用 successRedirect .在该路由中,我向LinkedIn发出了一个 GET 请求,以访问有关该用户的一些数据.我想将此数据存储在我的数据库中,并记住登录的用户.这是我的操作方式:

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);
                    });
                }

            });
    });
    }
);

让我在那里解释代码.获取用户数据后,我检查接收到的字段"id".如果此ID与存储在数据库中的我的用户的 linkedinLogin 字段之一匹配,则我认为它已注册(已在数据库中找到该用户),因此我必须登录他/她.我只是使用从 GET 请求中收到的数据创建一个新用户.

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.

在两种情况下,我的问题是-在数据库中找到用户,或者必须创建用户-每当与之交互时,如何设置 req.user 为我的用户我的网站?只需执行 req.user = userSearchResult (如果找到了用户,则在 if 语句内)或 req.user = user 就足够了(如果已创建用户,则在 newUser.save()回调内部),还是应该调用一些护照功能为我设置密码?

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?

与未使用LinkedIn登录的用户注册和登录有关的所有其他护照功能都可以正常工作.我只是担心要使此LinkedIn登录名与护照一起使用.

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.

谢谢.

passport.js将自动将 req.user 对象设置为您要作为的第二个参数传递的对象策略回调的完成功能.

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);
        })

    });
}));

我希望这会有所帮助.