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

使用passport.js和express.js(node.js)创建一个安全的oauth API,node.js,api,express,oauth,passport.js,Node.js,Api,Express,Oauth,Passport.js,我有一个特别的问题,除非我做得不对 我有一个包含两个方面的应用程序,一个客户端(html站点)和一个API(使用express+mongodb构建)。需要安全地访问API。他们都在不同的域上,现在让我们假设我的站点在domain.com上,我的API在API.com:3000上 我添加了passport,以便在使用用户的数据创建用户时从Github获取访问令牌,因此基本上我可以“使用Github登录” 我目前的程序是: 1) 客户端(站点)在API上打开一个弹出窗口 window.open("h

我有一个特别的问题,除非我做得不对

我有一个包含两个方面的应用程序,一个客户端(html站点)和一个API(使用express+mongodb构建)。需要安全地访问API。他们都在不同的域上,现在让我们假设我的站点在domain.com上,我的API在API.com:3000上

我添加了passport,以便在使用用户的数据创建用户时从Github获取访问令牌,因此基本上我可以“使用Github登录”

我目前的程序是:

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

window.open("http://api.com:3000/oauth")
2) 在express服务器上,启动passport进程:

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

});
对于策略,我使用了

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

在这一点上,一切都很好,我现在已登录到API。我的问题是如何将数据返回到客户端,因为客户端对accessToken、用户或用户id一无所知

因此,在客户端(打开弹出窗口的站点),我尝试了不同的方法:

  • 从弹出窗口获取值:由于重定向,无法工作,我无法跟踪弹出窗口的javascript信息

  • 调用my API以获取会话中的“当前用户”,例如 还有一个要求,不理想,但这一个有效。然而,我仍然有一个问题

如果我从浏览器访问此url,则当前url将返回用户,因为浏览器会在标头中发送请求express session cookie:

Cookie:connect.sid=s%3AmDrM5MRA34UuNZqiL%2BV7TMv6.Paw6O%2BtnxQRo0vYNKrher026CIAnNsHn4OJdptb8KqE
问题是我需要从jquery或类似的地方发出这个请求,这就是它失败的原因,因为会话没有被发送。因此,不会返回用户:

app.get('/current', function() {
    // PROBLEM HERE, req.user is undefined with ajax calls because of the session!
});
我找到了一种让它工作的方法,但我不满意,因为我会有跨浏览器的CORS问题,它增加了express:

res.header("Access-Control-Allow-Credentials", "true");
并在jquery ajax调用中添加withCredentials字段,如前所述

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

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
});
我对此也不满意,因为我正在丢失标题上的通配符:
Access Control Allow Origin
,如前所述,我需要指定一个域

因此,我不确定这里应该采用什么方法,我唯一需要的是客户端从passport oauth进程获取accessToken或用户ID。其思想是在对API的每次调用中使用该令牌来验证调用


有什么线索吗?

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

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

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

POST /login
  • 用户名和密码在正文中传递
  • 使用本地策略进行身份验证
  • 响应返回用户对象,包括访问令牌
GET/endpoint/abc123?访问令牌=abcdefg

  • 从登录响应中获取的令牌
  • 使用承载策略的身份验证(在passport http承载中)
现在Express中不需要会话


我希望此选项有帮助。

在express app中配置任何内容之前,请使用以下(完全相同)设置跨域响应的标题:

app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if ('OPTIONS' == req.method) {
     res.send(200);
 } else {
     next();
 }
});

你找到什么了吗?我也有同样的问题:(你可以看到我关于相同的答案。这对我很有效。我也使用了令牌。但是,我使用了带有授权头的承载身份验证策略。然后使用Express using Passport HTTP Bear:关于令牌生成,拥有一个永不过期的令牌是否安全?我是否必须使令牌过期并生成新的令牌一个?我想到的令牌就像我想到的密码一样——一些网站会自动让它们过期(如OAuth),而另一些则不会(如Amazon Web服务)。如果您将令牌视为密码—永远不要通过不安全的HTTP传递它,在数据库中加密它们,允许用户手动重新生成,等等,那么您可能不需要自动过期。不同的人对安全性和可用性有不同的阈值。如何确保令牌不能被拦截和重播?如果您无法重新生成因此,必须尽快使代币过期。您能逐行解释一下sintax的含义吗?如果我不使用它怎么办?
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if ('OPTIONS' == req.method) {
     res.send(200);
 } else {
     next();
 }
});