passport.js RESTful的身份验证 [英] passport.js RESTful auth

查看:263
本文介绍了passport.js RESTful的身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用passport.js如何一个把手认证(本地和Facebook等),通过一个RESTful API,而不是通过一个web界面?

How does one handle authentication (local and Facebook, for example) using passport.js, through a RESTful API instead of through a web interface?

具体问题正在处理数据的传递从回调到一个RESTful响应(JSON)与使用典型res.send({数据:req.data}),设置初始/登录端点被重定向至Facebook(/登录无法通过AJAX来访问,因为它不是一个JSON响应 - 这是一个重定向至Facebook与回调)

Specific concerns are handling the passing of data from callbacks to a RESTful response (JSON) vs using a typical res.send({ data: req.data }), setting up an initial /login endpoint which redirects to Facebook (/login cannot be accessed via AJAX, because it is not a JSON response - it is a redirect to Facebook with a callback).

我发现<一个href=\"https://github.com/halrobertson/test-restify-passport-facebook\">https://github.com/halrobertson/test-restify-passport-facebook,但我无法理解它。

I've found https://github.com/halrobertson/test-restify-passport-facebook, but I'm having trouble understanding it.

此外,如何passport.js存储权威性凭据?服务器(或者是服务?)是MongoDB的支持,而我期望凭证(登录名和放大器; PW的盐渍哈希)存储在那里,但我不知道是否有passport.js这种类型的能力。

Furthermore, how does passport.js store the auth credentials? The server (or is it service?) is backed by MongoDB, and I'd expect credentials (login & salted hash of pw) to be stored there, but I don't know if passport.js has this type of capability.

推荐答案

有在这里问了很多问题,看来,即使问题被问节点的背景和passport.js的真正的问题是更多的工作流程不是如何与一个特定的技术做到这一点。

There are many questions asked here, and it seems that even though the questions are asked in the context of Node and passport.js the real questions are more about workflow than how to do this with a particular technology.

让我们用@Keith示例设置,修改了一下以增加安全性:

Let's use @Keith example setup, modified a bit for added security:


    https://example.com
  • Web服务器提供一个页面的JavaScript客户端应用程序

  • https://example.com/api RESTful Web服务提供了丰富的客户端应用程序服务器支持

  • 服务器在节点和passport.js实施。

  • 服务器有一个数据库(任何形式)以用户表。

  • 的用户名/密码和Facebook连接提供身份验证选项

  • 富客户端让REST请求到 https://example.com/api

  • 有可能是其他客户端(手机应用程序,例如)使用网络服务在 https://example.com/api ,但不知道的网页在 https://example.com 服务器。

  • Web server at https://example.com serves a single page Javascript client app
  • RESTful web service at https://example.com/api provides server support to rich client app
  • Server implemented in Node and passport.js.
  • Server has a database (any kind) with a "users" table.
  • Username/password and Facebook Connect are offered as authentication options
  • Rich client makes REST requests into https://example.com/api
  • There may be other clients (phone apps, for example) that use the web service at https://example.com/api but do not know about the web server at https://example.com.

请注意,我使用安全HTTP。这是在我看来,任何服务必须是在公开可用的,因为像密码和授权令牌的敏感信息被客户端和服务器之间传递。

Note that I'm using secure HTTP. This is in my opinion a must for any service that is available in the open, since sensitive information like passwords and authorization tokens are passing between client and server.

让我们来看看旧的认证是如何工作的平原第一。

Let's look at how plain old authentication works first.


  • 的用户连接到 https://example.com

  • 服务器提供丰富的JavaScript应用这使得初始页面。 Somehwere页面有一个登录表单。

  • 很多这种单页的应用程序的各个部分都没有被填充数据,由于没有登录用户。所有这些部分有一个登录事件的事件侦听器。这一切都是客户端的东西,服务器不知道这些事件的。

  • 用户输入他/她的登录名和密码并点击了提交按钮,触发JavaScript处理记录在客户端变量的用户名和密码。然后,该处理程序触发登录事件。再次,这是所有客户端操作,凭据没有被发送到服务器尚未

  • 登录事件的监听器调用。每个这些现在需要在 https://example.com/api 发送一个或多个请求的REST风格的API来获取用户特定的数据呈现在页面上。他们发送给Web服务的每一个请求将包括用户名和密码,可能是在HTTP 基本认证的形式,因为该服务是基于REST不允许从一个请求到下一​​个维护客户端的状态。由于Web服务是安全的HTTP密码是在运输过程中安全加密。

  • https://example.com/api Web服务收到了一堆个人的请求,每个认证信息。在每个请求的用户名和密码对用户数据库检查,如果找到正确的请求的函数执行和数据被返回到JSON格式的客户端。如果用户名和密码不匹配错误,则发送到客户端的HTTP 401错误code的形式。

  • 而不是强制客户端每发送用户名和密码的要求,你可以有一个get_access_token功能在你的RESTful服务,需要用户名和密码,并响应与一个道理,这是某种形式的加密散列的,是独特和具有与之相关联的一些有效日期。这些令牌存储在与每个用户的数据库。然后,客户机将在后续请求访问令牌。访问令牌随后将针对数据库,而不是用户名和密码验证。

  • 像手机应用非浏览器客户端应用程序与上面相同,他们要求用户输入他/她的凭据,然后与每个请求的web服务给他们(或者从他们中产生一个访问令牌)。

  • The user connects to https://example.com
  • The server serves a rich Javascript application which renders the initial page. Somehwere in the page there is a login form.
  • Many of the sections of this single page app haven't been populated with data due to the user not being logged in. All these sections have an event listener on a "login" event. All this is client side stuff, the server does not know of these events.
  • User enters his/her login and password and hits the submit button, which triggers a Javascript handler to record the username and password in client side variables. Then this handler triggers the "login" event. Again, this is all client side action, credentials were not sent to the server yet.
  • The listeners of the "login" event are invoked. Each of these now needs to send one or more requests to the RESTful API at https://example.com/api to obtain the user specific data to render on the page. Every single request they send to the web service will include the username and password, possibly in the form of HTTP Basic authentication, since the service being RESTful isn't allowed to maintain client state from one request to the next. Since the web service is on secure HTTP the password is safely encrypted during transit.
  • The web service at https://example.com/api receives a bunch of individual requests, each with authentication information. The username and password in each request is checked against the user database and if found correct the requested function executes and data is returned to the client in JSON format. If username and password do not match an error is sent to the client in the form of a 401 HTTP error code.
  • Instead of forcing clients to send username and password with every request you can have a "get_access_token" function in your RESTful service that takes the username and password and responds with a token, which is some sort of cryptographic hash that is unique and has some expiration date associated with it. These tokens are stored in the database with each user. Then the client sends the access token in subsequent requests. The access token will then be validated against the database instead of the username and password.
  • Non browser client applications like phone apps do the same as above, they ask user to enter his/her credentials, then send them (or an access token generated from them) with every request to the web service.

从这个例子中的重要带走的一点是, REST风格的Web服务需要身份验证的每个请求

The important take away point from this example is that RESTful web services require authentication with every request.

在这种情况下的安全性的附加层将除了用户认证添加客户端应用程序的授权。例如,如果您有Web客户端,iOS和Android应用都使用Web服务,您可能希望在服务器知道哪些三者的定请求的客户端,无论谁的认证用户。这可以让你的web服务,以限制某些功能对特定的客户端。为此,你可以使用API​​密钥和秘密,请参见这个答案有关的一些想法。

An additional layer of security in this scenario would add client application authorization in addition to the user authentication. For example, if you have the web client, iOS and Android apps all using the web service you may want the server to know which of the three the client of a given request is, regardless of who the authenticated user is. This can enable your web service to restrict certain functions to specific clients. For this you could use API keys and secrets, see this answer for some ideas on that.

该工作流上述连接Facebook,因为通过Facebook登录有一个第三方,Facebook的本身不工作。登录过程需要被重定向到Facebook的网站,凭据我们的控制之外输入的用户。

The workflow above does not work for Facebook connect because the login via Facebook has a third party, Facebook itself. The login procedure requires the user to be redirected to Facebook's website where credentials are entered outside of our control.

让我们看看事情如何变化:

So let's see how things change:.


  • 的用户连接到 https://example.com

  • 服务器提供丰富的JavaScript应用这使得初始页面。 Somehwere在页面中有包括按钮与Facebook Login的登录表单。

  • 用户点击登录与Facebook按钮,这是只是重定向到一个链接(例如) https://example.com/auth/facebook

  • https://example.com/auth/facebook 路由是由passport.js处理(见的文档

  • 所有用户看到的是,网页的变化,现在他们都在一个网站托管,他们需要登录,并授权我们的Web应用程序页面。这是完全在我们的控制之外。

  • 的用户登录到Facebook和授予权限,以我们的应用程序,因此Facebook目前重定向回我们在passport.js设置,它下面的的documentation https://example.com/auth/facebook/callback

  • 的passport.js处理程序 https://example.com/auth/facebook/callback 路线将调用接收Facebook的访问令牌和一些回调函数从Facebook的用户信息,包括用户的电子邮件地址。

  • 的电子邮件,我们可以找到在我们的数据库中的用户和Facebook的访问令牌存储它。

  • 您在Facebook的回调做的最后一件事是重新回到富客户端应用程序,但是这个时候我们就需要用户名和访问令牌传递给客户端,以便它可以使用它们。这可以以多种方式来完成。例如,使用Javascript变量可以通过服务器侧模板引擎被加入到页,要不然一个cookie可以用这个信息被返回。 (感谢@RyanKimber与在URL中传递这些数据指出了安全问题,因为我最初建议)。

  • 现在我们开始单页的应用程序一次,但客户端的用户名和访问令牌。

  • 客户端应用程序可以立即触发登录事件,让应用程序要求的不同部分,他们从Web服务所需要的信息。

  • 发送到 https://example.com/api
  • 所有的请求将包括来自Facebook的令牌生成通过认证的Facebook的访问令牌,或者应用程序本身的访问令牌在REST API在get_access_token功能。

  • 非浏览器的应用程序都在这里有点难度,因为OAuth的要求用于登录Web浏览器。要通过手机或桌面应用程序登录,您将需要启动浏览器做重定向至Facebook,甚至更糟的是,你需要一种方法为浏览器通过Facebook的访问令牌回通过某种机制的应用程序。

  • The user connects to https://example.com
  • The server serves a rich Javascript application which renders the initial page. Somehwere in the page there is a login form that includes a "Login with Facebook" button.
  • The user clicks the "Login with Facebook" button, which is just a link that redirects to (for example) https://example.com/auth/facebook.
  • The https://example.com/auth/facebook route is handled by passport.js (see the documentation)
  • All the user sees is that the page changes and now they are in a Facebook hosted page where they need to login and authorize our web application. This is completely outside of our control.
  • The user logs in to Facebook and gives permission to our application, so Facebook now redirects back to the callback URL that we configured in the passport.js setup, which following the example in the documentation is https://example.com/auth/facebook/callback
  • The passport.js handler for the https://example.com/auth/facebook/callback route will invoke the callback function that receives the Facebook access token and some user information from Facebook, including the user's email address.
  • With the email we can locate the user in our database and store the Facebook access token with it.
  • The last thing you do in the Facebook callback is to redirect back to the rich client application, but this time we need to pass the username and the access token to the client so that it can use them. This can be done in a number of ways. For example, Javascript variables can be added to the page through a server-side template engine, or else a cookie can be returned with this information. (thanks to @RyanKimber for pointing out the security issues with passing this data in the URL, as I initially suggested).
  • So now we start the single page app one more time, but the client has the username and the access token.
  • The client application can trigger the "login" event immediately and let the different parts of the application request the information that they need from the web service.
  • All the requests sent to https://example.com/api will include the Facebook access token for authentication, or the application's own access token generated from Facebook's token via a "get_access_token" function in the REST API.
  • The non-browser apps have it a bit more difficult here, because OAuth requires a web browser for logging in. To login from a phone or desktop app you will need to start a browser to do the redirect to Facebook, and even worse, you need a way for the browser to pass the Facebook access token back to the application via some mechanism.

我希望这回答了大部分问题。当然你也可以与Twitter,谷歌或其他任何基于OAuth认证服务取代Facebook的。

I hope this answers most of the questions. Of course you can replace Facebook with Twitter, Google, or any other OAuth based authentication service.

我很想知道,如果有人有一个简单的方法来处理这​​个问题。

I'd be interested to know if someone has a simpler way to deal with this.

这篇关于passport.js RESTful的身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆