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

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

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

我已经添加了护照从Github获取访问令牌,因为我使用他们的数据创build了我的用户,所以我可以基本上有一个“用Githublogin”。

我目前的过程是:

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

window.open("http://api.com:3000/oauth") 

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

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

对于这个策略,我使用了这个代码 。

3)我将callbackredirect到一个url,closurespopup窗口(JavaScript与window.close()):

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

在这一点上,一切都很好,我现在login在API中。 我的问题是如何将数据返回给客户端,因为客户端还不了解accessToken,用户或用户ID。

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

  • 从popup窗口中获取值:由于redirect而不工作,我失去了popup式JavaScript信息的轨道

  • 调用我的API来获取会话中的“当前用户”,如http://api.com:3000/current另外一个请求,并不理想,但是这个工作。 但是,我仍然有一个问题。

如果我从浏览器到达它,这个/当前url正在返回用户,因为浏览器在头部请求中发送快速会话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! }); 

我find了一种方法使其工作,但我不满意,因为我将有跨浏览器的CORS问题,它是增加expression:

 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 ,我需要指定一个域,如此处所述。

所以,我不确定我应该采取的方法,唯一需要的是客户端从护照oauth进程获取accessToken或userID。 这个想法是在API的每个调用中使用该标记来validation调用。

任何线索?

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

正如你所说,解决scheme是使用CORS,以便使用XMLHTTPRequest在cookie中传递会话ID。

我没有使用在所有browswers上还没有工作的CORS,而是在其他请求上使用访问令牌。 我使用的工作stream程如下:

 POST /login 
  • 用户名和密码传入正文。
  • 使用本地策略的authentication。
  • 响应返回用户对象,包括access_token

GET / endpoint / abc123?access_token = abcdefg

  • 令牌从login响应中获得
  • 使用承载策略进行身份validation(在护照 – http-bearer中)

Express中现在不需要会话。

我希望这个替代有帮助。

在快速应用程序中configuration任何内容之前,请使用以下内容(完全相同)设置跨域响应的标题:

 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(); } });