使用 Passport 和 OAuth2 + 社交网络的 NodeJS REST 身份验证 [英] NodeJS REST authentication using Passport and OAuth2 + social network

查看:26
本文介绍了使用 Passport 和 OAuth2 + 社交网络的 NodeJS REST 身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 NodeJS 开发 REST api.对于身份验证,我决定使用 Passport.我想要真正的 RESTful api.所以这意味着我必须使用令牌而不是会话.

I'm working on REST api using NodeJS. For authentication I decided to use Passport. I want truly RESTful api. So it means I have to use tokens instead of sessions.

我想让用户使用用户名和密码登录,或者使用 Facebook、Google 和 Twitter 等社交网络.

I want to let users login using username and password, or using social networks like Facebook, Google and Twitter.

我制作了自己的 OAuth2.0 服务器,用于使用 oauth2orize 模块发布 AccessRefresh 令牌.所以现在我可以注册新用户,然后向他们颁发令牌.我跟着这个教程:

I make my own OAuth2.0 server for issuing Access and Refresh tokens using oauth2orize module. So now I can register new user and then issue them tokens. I followed this tutorial:

http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/

验证用户的路线:

// api ------------------------------------------------------------------------------------
    app.get('/api/userInfo',
        passport.authenticate('bearer', { session: false }),
        function(req, res) {
            // req.authInfo is set using the `info` argument supplied by
            // `BearerStrategy`.  It is typically used to indicate scope of the token,
            // and used in access control checks.  For illustrative purposes, this
            // example simply returns the scope in the response.
            res.json({ user_id: req.user.userId, name: req.user.username, scope: req.authInfo.scope })
        }
    );

所有这些都非常有效.不幸的是,我不知道如何实现社交身份验证.

All this works quite well. Unfortunately I don't know how to implement social authentication.

我正在阅读本教程:

http://scotch.io/tutorials/javascript/easy-node-authentication-facebook 

但在本教程中,他们并没有制作真正的 RESTful api.我已经根据本教程实现了用户架构,其中本地用户的令牌存储在单独的模型中.

But in this tutorial they are not making a truly RESTful api. I already implemented user schema according this tutorial where tokens for local user are stored in separated models.

// define the schema for our user model
var userSchema = mongoose.Schema({
    local: {
        username: {
            type: String,
            unique: true,
            required: true
        },
        hashedPassword: {
            type: String,
            required: true
        },
        created: {
            type: Date,
            default: Date.now
        }
    },
    facebook: {
        id: String,
        token: String,
        email: String,
        name: String
    },
    twitter: {
        id: String,
        token: String,
        displayName: String,
        username: String
    },
    google: {
        id: String,
        token: String,
        email: String,
        name: String
    }
});

但是现在,我如何验证用户?

But now, how can I verify user?

passport.authenticate('bearer', { session: false }),

这只是针对我的数据库验证不记名令牌,但我如何验证社交令牌?我错过了什么吗?

this is verifying only bearer token against to my db, but how can I verify social tokens? Am I missing something?

推荐答案

我将 Facebook 登录用于我自己的 我的记事本应用程序在这里.我开始时将应用程序用作网页,但登录后的通信仍将通过 API 进行.

I am using Facebook login for my own RESTful API for my Notepads app here. I started the application as one that will be used as a web page but still the communication after the login will be through the API.

然后我决定创建一个 同一应用的移动版本,它将使用应用程序接口.我决定这样做:移动应用程序通过 Facebook 登录并将 Facebook 用户 ID 和 FB 访问令牌发送到 API,API 调用 Facebooks 的 API 来验证这些参数,如果成功注册新用户(或登录现有的一个)在我的应用程序的数据库中,为此用户创建一个自定义令牌并将其返回到移动应用程序.移动应用从这里发送此自定义令牌以使用 API 对应用进行身份验证.

Then I decided to create a mobile version of the same app that will use the API. I decided to make it that way: The mobile app logs in through Facebook and sends the facebook user id and FB access token to the API, the API calls Facebooks's API to verify these params and if successful registers a new user(or logs in an existing one) in my app's DB, creates a custom token for this user and returns it to the mobile app. From here the mobile app sends this custom token to authenticate the app with the API.

这是一些代码:

API 中的 auth(使用 fbgraph npm 模块):

The auth in the API (uses the fbgraph npm module):

var graph = require('fbgraph'),
Promise = require('bluebird')
...
Promise.promisify(graph.get);
...
var postAuthHandler = function (req, res) {
    var fbUserId = req.body.fbId,
    fbAccessToken = req.body.fbAccessToken,
    accessToken = req.body.accessToken;
    ...
    graph.setAppSecret(config.facebook.app.secret);
    graph.setAccessToken(fbAccessToken);

    var graphUser;
    var p = graph.getAsync('me?fields=id,name,picture')
        .then(function (fbGraphUser) {
            //when the given fb id and token mismatch:
            if (!fbGraphUser || fbGraphUser.id !== fbUserId) {
                console.error("Invalid user from fbAccessToken!");
                res.status(HttpStatus.FORBIDDEN).json({});
                return p.cancel();
            }

            graphUser = fbGraphUser;

            return User.fb(fbUserId);
        })
        .then(function (user) {
            if (user) {
                //user found by his FB access token
                res.status(HttpStatus.OK).json({accessToken: user.accessToken});
                //stop the promises chain here
                return p.cancel();
            }
            ...create the user, generate a custom token and return it as above...

noreferr="https://github.com/iliyan-trifonov/notepads-nodejs-angularjs-mongodb-bootstrap/blob/6617a5cb418ba8acd6351ef9a9f69228f1047154/src/routes/users.js#L46.

用户模型:

var userSchema = new mongoose.Schema({
    facebookId: { type: String, required: true, unique: true },
    accessToken: { type: String, required: true, unique: true },
    name: { type: String, required: true },
    photo: { type: String, required: true },
    categories: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Category' }],
    notepads: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Notepad' }]
});

https://github.com/iliyan-trifonov/notepads-nodejs-angularjs-mongodb-bootstrap/blob/master/src/models/user.js#L9 .

移动应用中的 Facebook 身份验证:

The Facebook auth in the mobile app:

               auth: function(fbId, fbAccessToken) {
                return $http({
                    url: apiBase + '/users/auth',
                    data: {
                        fbId: fbId,
                        fbAccessToken: fbAccessToken
                    },
                    method: 'POST',
                    cache: false
                });
            },
            ...

https://github.com/iliyan-trifonov/notepads-ionic/blob/master/www/js/services.js#L33 .

移动应用发送带有请求的令牌:

The mobile app sends the token with the request:

  notepads: {
            list: function() {
                return $http({
                    url: apiBase + '/notepads?insidecats=1' + '&token=' + User.get().accessToken/*gets the token from the local storage*/,
                    method: 'GET',
                    cache: false
                });
            },

这是一个 Ionic/Angular/Cordova 应用程序.从移动应用程序登录 Facebook 会启动安装在您手机上的 Facebook 应用程序或打开一个弹出窗口以登录 Facebook.然后回调将 Facebook 用户的 ID 和访问令牌返回到我的移动应用.

It's an Ionic/Angular/Cordova app. The Facebook login from the mobile app starts the Facebook app installed on your phone or opens a popup to login in Facebook. Then a callback returns the Facebook user's id and access token to my mobile app.

fbgraph npm 模块:https://github.com/criso/fbgraph

The fbgraph npm module: https://github.com/criso/fbgraph

这篇关于使用 Passport 和 OAuth2 + 社交网络的 NodeJS REST 身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆