使用Passport和OAuth2 +社交网络进行NodeJS REST身份验证

San*_*dak 21 node.js access-token express facebook-access-token passport.js

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

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

我创建自己的OAuth2.0服务器来发布AccessRefresh tokens使用oauth2orize模块.所以现在我可以注册新用户,然后发出令牌.我按照本教程:

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 })
        }
    );
Run Code Online (Sandbox Code Playgroud)

这一切都很有效.不幸的是我不知道如何实现社会认证.

我正在阅读本教程:

http://scotch.io/tutorials/javascript/easy-node-authentication-facebook 
Run Code Online (Sandbox Code Playgroud)

但在本教程中,他们并没有制作真正的RESTful API.我已根据本教程实现了用户模式,其中本地用户的标记存储在单独的模型中.

// 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
    }
});
Run Code Online (Sandbox Code Playgroud)

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

passport.authenticate('bearer', { session: false }),
Run Code Online (Sandbox Code Playgroud)

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

Ili*_*nov 7

我在这里我的Notepads应用程序使用Facebook登录我自己的RESTful API .我启动了一个将用作网页的应用程序,但登录后仍然通过API进行通信.

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

这是一些代码:

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

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...
Run Code Online (Sandbox Code Playgroud)

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' }]
});
Run Code Online (Sandbox Code Playgroud)

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

移动应用中的Facebook认证:

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

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

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

  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
                });
            },
Run Code Online (Sandbox Code Playgroud)

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

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