使用passport.js和express.js(node.js)创建一个安全的oauth API

Sou*_*tep 18 api oauth node.js express passport.js

我有一个特定的问题,除非我没有以正确的方式做事.

我有一个带有双方的应用程序,一个客户端(html站点)和一个API(用express + mongodb构建).需要安全地访问API.他们都在不同的域名,现在让我们说我的网站在domain.com上,我的API在api.com:3000上.

我已经添加了护照来从Github获取访问令牌,因为我正在用他们的数据创建我的用户,所以我可以基本上"登录Github".

我目前的流程是:

1)客户端(站点),在API上打开一个弹出窗口

window.open("http://api.com:3000/oauth")
Run Code Online (Sandbox Code Playgroud)

2)快递服务器,启动护照流程:

app.get('/oauth', passport.authenticate('github'), function(req, res) {

});
Run Code Online (Sandbox Code Playgroud)

对于策略,我使用了这段代码.

3)我将回调重定向到关闭弹出窗口的URL(带有window.close()的javascript):

app.get('/oauth/callback', passport.authenticate('github', { failureRedirect: '/' }), function(req, res) {
    res.redirect('/auth_close');
});
Run Code Online (Sandbox Code Playgroud)

那时,一切都很好,我现在登录了API.我的问题是如何将数据返回给客户端,因为客户端还不知道任何有关accessToken,用户或用户ID的信息.

所以,从客户端(打开弹出窗口的网站),我尝试了不同的方法:

  • 从弹出窗口获取值:由于重定向不起作用,我忘记了弹出的javascript信息

  • 调用我的API来获取会话中的"当前用户",例如http://api.com:3000/current还有 一个请求,不理想,但这个工作.但是,我还是有问题.

如果我从浏览器访问该用户,则此/ url将返回用户,因为浏览器在标头请求中发送快速会话cookie:

Cookie:connect.sid=s%3AmDrM5MRA34UuNZqiL%2BV7TMv6.Paw6O%2BtnxQRo0vYNKrher026CIAnNsHn4OJdptb8KqE
Run Code Online (Sandbox Code Playgroud)

问题是我需要从jquery或类似的地方发出这个请求,因为会话没有发送,所以它就失败了.所以用户不会被退回:

app.get('/current', function() {
    // PROBLEM HERE, req.user is undefined with ajax calls because of the session!
});
Run Code Online (Sandbox Code Playgroud)

我发现了一种让它工作的方法,但我不满意因为我会有跨浏览器的CORS问题,它正在添加表达:

res.header("Access-Control-Allow-Credentials", "true");
Run Code Online (Sandbox Code Playgroud)

并添加withCredentials场jQuery的AJAX调用,如解释在这里.

要在本机XHR对象上设置的fieldName-fieldValue对的映射.例如,如果需要,您可以使用它将withCredentials设置为true以用于跨域请求.

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
});
Run Code Online (Sandbox Code Playgroud)

我也不满意,这是我失去了我的头通配符:Access-Control-Allow-Origin我需要指定域,作为解释在这里.

所以,我不确定我应该采取的方法,我唯一需要的是客户端从护照oauth进程获取accessToken或userID.这个想法是在每次调用API时使用该令牌来验证调用.

任何线索?

Sco*_*zer 13

我遇到过同样的问题.我在登录页面上使用本地策略,然后检查用户是否在其他请求的会话中.

正如您所说,解决方案是使用CORS,以便使用XMLHTTPRequest在cookie中传递会话ID.

我没有使用尚未在所有浏览器上工作的CORS,而是在其他请求中使用访问令牌.我使用的工作流程如下:

POST /login
Run Code Online (Sandbox Code Playgroud)
  • 用户名和密码在正文中传递.
  • 使用本地策略进行认证
  • Response返回用户对象,包括access_token

GET/endpoint/abc123?access_token = abcdefg

  • 令牌从登录响应中获取
  • 使用承载策略进行认证(在护照-http-bearer中)

Express中现在不需要会话.

我希望这个替代方案有所帮

  • 我认为令牌像是我想到的密码 - 有些网站会自动过期(例如像OAuth),而其他网站则没有(例如亚马逊网络服务).如果您将令牌视为密码 - 永远不会通过非安全HTTP传递它,在数据库中加密它们,允许用户手动重新生成等等,那么您可能不需要自动过期.不同的人对安全性和可用性有不同的阈值. (4认同)