具有单独的网站和API服务器的同构Web应用程序的身份验证

13 architecture security authentication api oauth

我在api.com上的服务器上开发了一个无状态API.某些API端点需要身份验证.

我有一个网站在一个单独的服务器上website.com.当用户对网站进行身份验证时,网站服务器需要从API端点检索一些需要身份验证的数据(/tweets例如).此数据将用于服务器响应(例如,呈现推文).

服务器响应还将在浏览器中下载一些JavaScript,随后需要从需要身份验证的API端点(/tweets例如,通过XMLHttpRequests(XHR))检索一些数据.

此体系结构表示同构Web应用程序.服务器在请求时呈现整个页面,然后客户端使用JavaScript处理用户操作.

-

在非常基础的层面上,我可以对website.com和api.com使用HTTP基本身份验证.但是,浏览器会提示用户在首次登录website.com时输入凭据,并在客户端向需要身份验证的端点进行XHR时反复进行.

我希望用户在website.com上使用他们的凭据登录一次.这与当前的Twitter网站类似.登录到twitter.com后,网站服务器会将您识别为已通过身份验证,并使用包含JavaScript下载的HTML页面进行响应.然后,JavaScript应用程序(可能)将经过身份验证的XHR发送到无状态Twitter API.

API是一个单独的服务器设计.最终API可以为第三方开放,尽管这不是最初的要求.

我怎样才能做到这一点?我在找:

  • 最简单的安全解决方案
  • 使用OAuth的解决方案(如果适用)

两者都很棒!

Jul*_*ian 10

您描述的情况正是OAuth的设计目标:客户端使用一台服务器进行授权,然后获取对另一台服务器上资源的访问权限.在您的情况下,website.com是授权服务器,api.com是资源服务器.简而言之,授权服务器向客户端发送访问令牌,然后客户端可以将访问令牌传递给资源服务器以证明他们有权访问资源.为了使其工作,资源服务器(api.com)需要使用授权服务器(website.com)进行检查以验证令牌是有效的还是事先被告知令牌.因此,客户端,授权服务器和资源服务器之间存在三角形通信,其中传递共享密钥.因此,绝对有必要在链的所有部分使用安全连接(HTTPS); 否则,有人可以拦截令牌并伪装成授权客户.通过使用无法完全验证用户身份的有限访问令牌,将其保持在合理范围内,但仍然是您应该尝试防止的问题.

虽然理论上是安全的,但OAuth是一个复杂的系统,很难做到正确.有些人认为实际上不可能做对(尤其是Eran Hammer,OAuth 2.0规范的原始主要作者,他决定退出工作组).但是,鉴于您无论如何都需要使用HTTPS,您可以完全避免使用OAuth,而是使用一种鲜为人知的HTTPS内置功能(或实际上是TLS)称为(惊奇!)客户端身份验证.

您可能已经知道,在HTTPS协议中,服务器(website.com)使用由受信任的机构签名的证书来验证自身.这是一个很好理解且非常安全的机制(至少通过互联网标准),只要证书不妥协并且使用最新版本的TLS.客户端也可以这样做,即使用由受信任的机构签名的证书进行身份验证.后一个权限可以是服务器(website.com),因为服务器可以信任自己.因此,TLS客户端身份验证的优雅之处在于客户端无需联系第三方即可获取证书; 客户端和服务器可以合作为客户端提供服务器可以信任的证书.这甚至可能非常用户友好,因为客户端证书只需要传输和安装一次,然后可以用于后续会话的身份验证,可能没有用户甚至需要输入密码.相同的客户端证书也可以用于与其他服务器(例如api.com)的HTTPS连接,前提是这些服务器知道证书并信任签署它的权限(website.com).

TLS客户端身份验证可能比OAuth更安全,但可能需要较少的用户整体交互(取决于在浏览器中处理客户端证书的方式).另一方面,大多数用户可能不熟悉TLS客户端身份验证的特定机制.如果用户需要从许多不同的设备登录或需要对许多不同的服务器进行身份验证,则此工作流可能会令人困惑或麻烦,因为每个设备都需要有证书,并且当新服务器时用户可能必须手动选择证书是第一次访问.

总结一下:

  • 在这两种情况下,website.com都为客户提供了一种授权访问api.com的方法,api.com需要了解这一点.所以api.com不能100%无国籍; 它需要了解website.com与客户沟通的授权方式.
  • 这两种情况都需要安全连接(HTTPS).
  • 在OAuth中,授权方式是"共享密钥"受限访问令牌(也称为"伪身份验证"),而在TLS客户端身份验证中,它是完全对客户端进行身份验证的私有证书,因为它是由受信任的颁发机构签名的.
  • 在OAuth中,授权在数据层上完成(应用程序显式传递访问令牌),而在TLS客户端身份验证中,身份验证在传输层完成(这意味着您的API实际上不需要知道身份验证甚至授权,如果Web服务器配置为仅允许某些端点通过身份验证的客户端).
  • TLS客户端身份验证可能更值得信赖,但OAuth可能对用户更为熟悉,因为它可以"像往常一样"使用密码登录.

对评论的一些澄清:

website.com如何知道用户已登录?website.com如何记住用户已登录(即浏览器刷新之间)?

通过将访问令牌存储在客户端的安全cookie中.在客户端对website.com的每个请求中,访问令牌都包含在请求标头中.这样,website.com可以确保每个请求都经过身份验证(如果请求包含访问令牌,即用户已登录),或者访问者是访客.

浏览器如何进行经过身份验证的XHR请求?

通过在请求标头中发送访问令牌,就像对于website.com一样.显然,这需要客户端访问cookie.

在创建服务器响应时,website.com需要通过api.com进行身份验证

当它这样做时,它只是代表用户发送(HTTPS)请求.访问令牌包含在请求标头中也是一样的.website.com在执行此操作时始终具有用户的访问令牌,因为它要么将其提供给用户,要么只是从用户接收它.


有关维基百科的更多信息:


Tim*_* Ha 0

我认为这样的事情可以做

1)用户登录website.com,website.com将创建一个临时令牌T以供将来API使用

2) 每当 api.com 需要某些数据时,网站都会请求该数据并在请求 api.com/getdata/params=...&token=T 中发送令牌 T

此请求最好使用 SSL 来完成,以保护令牌。

另请检查http://en.wikipedia.org/wiki/Cross-origin_resource_sharing - 并非所有浏览器都允许您从 Javascript 请求来自另一个域的数据。

3) 当 api.com 收到此类请求时,它将与 website.com 建立一个单独的秘密连接,例如 website.com/checktoken/?token=T 并在 website.com 上获取有关用户的所有必要信息以发送他的相关数据

4) 用户获取所有信息,无需离开 website.com,也无需在两个地方进行身份验证