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

2024-02-29

我正在尝试RESTapi使用NodeJS。为了进行身份验证,我决定使用Passport。我想要真正的 RESTful api。所以这意味着我必须使用令牌而不是会话。

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

我自己做OAuth2.0发行服务器Access and Refresh tokens using oauth2orize模块。所以现在我可以注册新用户,然后向他们颁发令牌。 我按照这个教程进行操作:

http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/ 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 })
        }
    );

所有这些都运作良好。不幸的是我不知道如何实施社会认证。

我正在阅读本教程:

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

但在本教程中,他们并没有制作真正的 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
    }
});

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

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

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


我正在使用 Facebook 登录作为我自己的 RESTful API我的记事本应用程序在这里 https://github.com/iliyan-trifonov/notepads-nodejs-angularjs-mongodb-bootstrap。我启动该应用程序时将其用作网页,但登录后的通信仍将通过 API 进行。

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

这是一些代码:

API 中的身份验证(使用 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...

https://github.com/iliyan-trifonov/notepads-nodejs-angularjs-mongodb-bootstrap/blob/6617a5cb418ba8acd6351ef9a9f69228f1047154/src/routes/users.js#L46 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 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
                });
            },
            ...

https://github.com/iliyan-trifonov/notepads-ionic/blob/master/www/js/services.js#L33 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
                });
            },

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Passport 和 OAuth2 + 社交网络的 NodeJS REST 身份验证 的相关文章

随机推荐

  • UIScrollView contentInset 属性有什么用?

    有人可以向我解释一下是什么吗contentInset财产在一个UIScrollView实例是用来做什么的 也许提供一个例子 它设置内容视图和封闭滚动视图之间的插图距离 Obj C aScrollView contentInset UIEdg
  • 解决 celerybeat 的单点故障问题

    我正在寻找推荐的解决方案来解决 celerybeat 成为 celery rabbitmq 部署的单点故障的问题 到目前为止 通过搜索网络 我没有找到任何有意义的东西 就我而言 定时调度程序每天启动一次可以运行半天或更长时间的一系列作业 由
  • contentView 在 iOS 6 UITableViewCell 原型单元格中不缩进

    我正在配置自定义UITableViewCell在故事板中使用原型单元 然而 所有的UILabels 和其他 UI 元素 似乎没有添加到单元格的contentView 而不是添加到UITableViewCell直接查看 当单元格进入编辑模式时
  • Chrome iframe 父级未定义

    我有这个 Gmail 脚本 它运行在canvas frame iframe 我想使用父文档的句柄parent document 但在 Chrome 中告诉我它是未定义的 在 Firefox 中工作正常 但在 Chrome 上就崩溃了 那么
  • 在SceneKit中,SCNLightTypeAmbient类型的SCNLight是否会忽略categoryBitMask参数?

    看来是啊 这里 categoryBitMask 被忽略 ambientLight SCNLight light ambientLight color UIColor colorWithRed 0 994 green 0 715 blue 0
  • iTunes 有哪些脚本目标?

    苹果有一个很好的文档技术问答页面 https developer apple com library mac qa qa1802 index html用于实现 Mail app 的脚本目标 然而 尽管脚本目标也适用于 iTunes 但没有可
  • 静态方法和扩展方法同名

    我创建了扩展方法 public static class XDecimal public static decimal Floor this decimal value int precision decimal step decimal
  • Vue2 在通过 Axios 接收的列表中搜索

    由于过滤比 Vue 1 中的过滤要复杂得多 所以我有一个问题 这是我的组件 其中显示了羊列表 并提供了搜索 过滤名称或家族的选项 但我不知道如何实现这一目标
  • 如何将配置变量发送到 py.test 测试?

    我有一个测试套件需要与多个后端一起运行 但这不是一个简单的参数化测试 因为它适用于整个套件 多个文件 模块 我可以通过环境控制运行 但我想知道 py test 是否有更清晰的方式来表达这一点 也就是说 我正在寻找这样的东西 py test
  • 如何将 hasOne 关系与嵌入的always关系建立起来

    EmberJS 在早期版本中删除了 hasOne 在我想要 hasOne 的地方创建这样的嵌套对象关系的方法是什么 已经删除了 hasOne 以支持 ownTo 任何人都可以分享一下如何在嵌套 JSON 之间编写 embedded alwa
  • 如何将 C++ 静态库链接到 C 程序?

    我有以下 C 程序 Client h ifndef Client Client h define Client Client h include Client h class Client public void f1 void f2 en
  • Vim 中切换回上一个窗口的快捷方式?

    Ctrlw1w switches to the first window 如果目前我经常在几个窗口中的两个中进行编辑 那么切换回最后一个活动窗口的快捷方式将是完美的 有这样的捷径吗 你试过了吗
  • javascript 动态 HTML 表格行导致问题

    我有一个select option在选择其中我创建一个 HTML 表 因为我根据所选选项从后端调用数据 所以创建的表行是动态的 我正在做的是 在更改选择选项时 我正在创建 HTML 表格行 这些行是动态的并且由输入字段组成 ItemName
  • “mod”Haskell 上的语法错误[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我正在关注 haskell 教程 http www seas upenn edu cis194 lectures 01 intro
  • Autohotkey 脚本使用命令行参数运行程序

    我正在使用自动热键来自动化一些手动过程 我必须运行一个接受几个命令行参数的java命令行程序 java 我想在自动化中执行一些预定义的任务后从 autohotkey 运行这个 java 程序 我该怎么做 我认为这就是您正在寻找的 在此示例中
  • OAuth2 与 Spring Security - InsufficientAuthenticationException

    我目前正在开发一个涉及 Spring Security 针对 OAuth2 的项目 我们正在使用授权码流程 但是 当客户端点击 AuthorizationEndpoint oauth authorize 时 我们得到一个 Insuffici
  • 是否可以让 LaTeX 链接到图形的顶部而不是其标题?

    在我的 TeX 文件中 我有以下代码 begin figure H begin center includegraphics width 5in screens main png caption label fig MainScreen S
  • 如何在 Objective-c 中将数组声明为常量?

    以下代码给我错误 constants h extern NSArray const testArray constants m NSArray const testArray NSArray arrayWithObjects foo bar
  • 教义:如何取消设置(SET NULL)OneToMany关系

    这是一个非常非常简单的行为 但我却找不到用教义来实现的方法 我将解释它仅用两个实体来降低复杂性 有两个相关的实体 作者和书籍 例如 一位作者拥有零本或更多书籍 和 一本书籍由零位或一位作者拥有 我试图取消作者与其一本书籍之间的关系 来自作者
  • 使用 Passport 和 OAuth2 + 社交网络的 NodeJS REST 身份验证

    我正在尝试RESTapi使用NodeJS 为了进行身份验证 我决定使用Passport 我想要真正的 RESTful api 所以这意味着我必须使用令牌而不是会话 我想让用户使用用户名和密码登录 或者使用 Facebook Google 和