简体   繁体   English

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

[英]Make a secure oauth API with passport.js and express.js (node.js)

I've got I think a specific problem, unless I'm not doing things in the right way. 我有一个特定的问题,除非我没有以正确的方式做事。

I've got an application with 2 sides, a client (html site), and an API (built with express + mongodb). 我有一个带有双方的应用程序,一个客户端(html站点)和一个API(用express + mongodb构建)。 The API will need to be securely accessed. 需要安全地访问API。 They both are on different domains, for now let's say my site is on domain.com and my API is on api.com:3000. 他们都在不同的域名,现在让我们说我的网站在domain.com上,我的API在api.com:3000上。

I've added passport to get an access token from Github as I'm creating my users with their data, so I can have a "Sign in with Github" basically. 我已经添加了护照来从Github获取访问令牌,因为我正在用他们的数据创建我的用户,所以我可以基本上“登录Github”。

My current process is: 我目前的流程是:

1) the client (the site), opens a popup on the API 1)客户端(站点),在API上打开一个弹出窗口

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

2) The express server, start the passport process: 2)快递服务器,启动护照流程:

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

});

For the strategy, I used this code . 对于策略,我使用了这段代码

3) I redirect the callback to a url that closes the popup (javascript with a window.close()): 3)我将回调重定向到关闭弹出窗口的URL(带有window.close()的javascript):

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

At that point, all is fine, I am now logged in the API. 那时,一切都很好,我现在登录了API。 My problem is how to get data back to the client, as the client doesn't know anything yet about accessToken, user or user id. 我的问题是如何将数据返回给客户端,因为客户端还不知道任何有关accessToken,用户或用户ID的信息。

So, from the client (the site that opens the popup), I tried different approaches: 所以,从客户端(打开弹出窗口的网站),我尝试了不同的方法:

  • getting a value from the popup: doesn't work because of the redirection, I lose track of the popup javascript information 从弹出窗口获取值:由于重定向不起作用,我忘记了弹出的javascript信息

  • calling my API to get the "current user" in session, such as http://api.com:3000/current One more request, not ideal, but this one work. 调用我的API来获取会话中的“当前用户”,例如http://api.com:3000/current还有一个请求,不理想,但这个工作。 However, I still have a problem. 但是,我还是有问题。

This /current url is returning the user if I reach it from the browser, because the browser send in the header request the express session cookie: 如果我从浏览器访问该用户,则此/ url将返回用户,因为浏览器在标头请求中发送快速会话cookie:

Cookie:connect.sid=s%3AmDrM5MRA34UuNZqiL%2BV7TMv6.Paw6O%2BtnxQRo0vYNKrher026CIAnNsHn4OJdptb8KqE

The problem is that I need to make this request from jquery or similar, and that's where it fails because the session is not sent. 问题是我需要从jquery或类似的地方发出这个请求,因为会话没有发送,所以它就失败了。 So the user is not returned: 所以用户不会被退回:

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

I found a way of making it work but I'm not happy with because I'll have cross-browsers CORS problems, it is adding to express: 我发现了一种让它工作的方法,但我不满意因为我会有跨浏览器的CORS问题,它正在添加表达:

res.header("Access-Control-Allow-Credentials", "true");

And add the withCredentials field in a jquery ajax call, as explained here . 并添加withCredentials场jQuery的AJAX调用,如解释在这里

A map of fieldName-fieldValue pairs to set on the native XHR object. 要在本机XHR对象上设置的fieldName-fieldValue对的映射。 For example, you can use it to set withCredentials to true for cross-domain requests if needed. 例如,如果需要,您可以使用它将withCredentials设置为true以用于跨域请求。

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
});

I am also not happy with this as I'm losing the wildcard on my header: Access-Control-Allow-Origin , I need to specify a domain, as explained here . 我也不满意,这是我失去了我的头通配符: Access-Control-Allow-Origin ,我需要指定域,作为解释在这里

So, I'm not sure the approach I should take here, the only thing I need is the client getting either an accessToken, or a userID back from the passport oauth process. 所以,我不确定我应该采取的方法,我唯一需要的是客户端从护照oauth进程获取accessToken或userID。 The idea is using that token in each call to the API to validate the calls. 这个想法是在每次调用API时使用该令牌来验证调用。

Any clue? 任何线索?

I had the same issue. 我遇到过同样的问题。 I was using the Local Strategy on the login page, and then checking to see if the user was on the session on other requests. 我在登录页面上使用本地策略,然后检查用户是否在其他请求的会话中。

As you say, the solution is to use CORS in order for the session ID to be passed in a cookie using XMLHTTPRequest. 正如您所说,解决方案是使用CORS,以便使用XMLHTTPRequest在cookie中传递会话ID。

Instead of using the CORS which does not yet work on all browswers, I deceided to use access tokens on other requests. 我没有使用尚未在所有浏览器上工作的CORS,而是在其他请求中使用访问令牌。 The workflow I used is as follows: 我使用的工作流程如下:

POST /login
  • Username and password get passed in the body. 用户名和密码在正文中传递。
  • Authentication using Local Strategy. 使用本地策略进行认证
  • Response returns the user object, including the access_token Response返回用户对象,包括access_token

GET /endpoint/abc123?access_token=abcdefg GET / endpoint / abc123?access_token = abcdefg

  • Token obtained from the login response 令牌从登录响应中获取
  • Authentication using Bearer Strategy (in passport-http-bearer) 使用承载策略进行认证(在护照-http-bearer中)

Sessions are now not needed in Express. Express中现在不需要会话。

I hope this alternative helps. 我希望这个替代方案有所帮

Before configuring anything in express app, use the following(exactly the same) to set header of response for cross-domain : 在快速应用程序中配置任何内容之前,请使用以下(完全相同的)为跨域设置响应标头:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Node.js理论-Node.js,Express.js,Passport.js - Node.js theory - Node.js, Express.js, Passport.js 尝试查看Express.js Node.js Passport.js中所有已登录的用户 - Trying to view all logged in Users in Express.js Node.js Passport.js Node.js + express.js + passport.js:在服务器重新启动之间保持身份验证 - Node.js + express.js + passport.js : stay authenticated between server restart Node.js + Express.js + Passport.js-我需要一些有关如何构建它们的建议 - Node.js + Express.js + Passport.js - i need some advice how to structure them Nginx + Node.js + express.js + passport.js:Subdommain保持身份验证 - Nginx + Node.js + express.js + passport.js: Subdommain stay authenticated Node.js 在 express.js/passport.js 中将参数传递给我的 require function? 明白为什么? - Node.js passing parameters to my require function in express.js/passport.js? understanding why? Node.js Express 4和Passport.js的CSRF保护不起作用 - CSRF protection for Node.js Express 4 and passport.js not working 带有Passport.js的Node.js微服务API网关 - Node.js microservices API Gateway with Passport.js 使用node.js进行Passport.js身份验证 - Passport.js authentication with node.js 如何使用 Express.js 和 Passport.js 重置 Oauth 身份验证批准 - How to reset Oauth authentication approval with Express.js and Passport.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM