OAuth 2.0:好处和应用场景 - 为什么?

295

有人能解释一下OAuth2的好处以及为什么我们应该实施它吗?我之所以问是因为我对此有些困惑,以下是我的当前想法:

OAuth1(更确切地说是HMAC)请求似乎逻辑清晰、易于理解和开发,并且非常安全。

反之,OAuth2引入了授权请求、访问令牌和刷新令牌,你必须在会话开始时进行3次请求才能获得所需数据。即使如此,当令牌过期时,你的其中一个请求最终也会失败。

而要获取另一个访问令牌,则需要使用同时传递的刷新令牌。那么从安全角度来看,访问令牌是否变得无用呢?

此外,就像/r/netsec最近展示的那样,SSL并不完全安全,因此将所有东西都转移到TLS/SSL上而不是安全的HMAC,这一点让我感到困惑。

OAuth认为这不是关于100%的安全性,而是关于发布和完成。这对供应商来说并不是很有前景。当它提到6种不同的流程时,我可以看到它试图实现什么,但它就是无法在我的脑海中形成连贯的整体。

我认为这可能更多是我难以理解其好处和原因,而不是真的不喜欢它,所以这可能有点无端攻击。如果这听起来像是抱怨,请原谅。


1
请看:https://dev59.com/nW855IYBdhLWcg3w1oLa - alexbilbie
3个回答

364

背景:我已经为OAuth 1.0a和2.0编写了客户端和服务器堆栈。

OAuth 1.0a和2.0都支持双向身份验证,其中服务器可以确保用户的身份,以及三方身份验证,其中内容提供者向服务器保证用户的身份。三方身份验证是授权请求和访问令牌发挥作用的地方,需要注意的是OAuth 1也有这些功能。

复杂的三方身份验证

OAuth规范的一个主要点是,内容提供者(例如Facebook、Twitter等)向服务器(例如希望代表客户端与内容提供者通信的Web应用程序)保证客户端具有某些身份。三方身份验证所提供的功能是在不需要客户端或服务器了解该身份的详细信息(例如用户名和密码)的情况下完成此操作。

不过,不深入讨论OAuth的细节:

  1. 客户端向服务器提交授权请求,服务器验证其是否是其服务的合法客户端。
  2. 服务器将客户端重定向到内容提供者,请求访问其资源。
  3. 内容提供者验证用户的身份,并经常请求其访问资源的权限。
  4. 内容提供者将客户端重定向回服务器,通知其成功或失败。此请求在成功时包括授权代码。
  5. 服务器对内容提供者进行一次带外请求,并用授权代码交换访问令牌。
服务器现在可以通过传递访问令牌代表用户向内容提供者发出请求。
每次交换(客户端->服务器,服务器->内容提供者)都包括共享密钥的验证,但由于OAuth 1可以在未加密的连接上运行,因此每个验证不能通过线路传递密钥。
正如您所指出的那样,这是通过HMAC完成的。客户端使用与服务器共享的密钥对其授权请求的参数进行签名。服务器获取参数,使用客户端的密钥对其进行签名,从而能够查看它是否是合法的客户端(在步骤1中)。
此签名要求客户端和服务器同意参数的顺序(以便它们签署完全相同的字符串),OAuth 1的主要抱怨之一是它要求服务器和客户端进行排序和签名。这是棘手的代码,要么正确,要么就会得到401未经授权的错误,而且帮助很少。这增加了编写客户端的障碍。
通过要求授权请求在SSL上运行,OAuth 2.0完全消除了参数排序和签名的需要。客户端将其密钥传递给服务器,服务器直接验证它。
服务器->内容提供者连接中也存在相同的要求,由于它是SSL,因此消除了访问OAuth服务的服务器的一个障碍。
这使得步骤1、2和5变得更加容易。
因此,我们的服务器现在具有永久访问令牌,该令牌相当于用户的用户名/密码。它可以通过将访问令牌作为请求的一部分(作为查询参数、HTTP头或POST表单数据)传递来代表用户向内容提供者发出请求。
如果内容服务仅通过SSL访问,那就没问题了。如果它可以通过普通HTTP访问,我们希望以某种方式保护该永久访问令牌。任何窃听连接的人都能永久地获得用户的内容。
在OAuth 2中解决这个问题的方法是使用"刷新令牌"。刷新令牌成为永久密码等效物,而且它只会在SSL上传输。当服务器需要访问内容服务时,它会用刷新令牌交换一个短暂的访问令牌。这样所有可被嗅探的HTTP访问都将使用即将过期的令牌。Google在其OAuth 2 API中使用5分钟的过期时间。
因此,除了刷新令牌,OAuth 2简化了客户端、服务器和内容提供者之间的所有通信。刷新令牌的存在仅是为了在未加密访问内容时提供安全性。
两步验证
有时候,服务器只需要控制对自己内容的访问。两步验证允许客户端直接与服务器验证用户。
OAuth 2标准化了一些广泛使用的OAuth 1扩展。我最了解的是Twitter引入的xAuth。你可以在OAuth 2中看到它作为资源所有者密码凭据
基本上,如果您信任客户端使用用户凭据(用户名和密码),他们可以直接与内容提供者交换这些凭据以获取访问令牌。这使得OAuth在移动应用程序上变得更加有用——在三个步骤的身份验证中,您必须嵌入HTTP视图,以处理与内容服务器的授权过程。
在OAuth 1中,这不是官方标准的一部分,并且需要与所有其他请求相同的签名过程。
我刚刚使用Resource Owner Password Credentials实现了OAuth 2的服务器端,从客户端的角度来看,获取访问令牌变得简单:从服务器请求访问令牌,将客户端ID /密钥作为HTTP授权头,将用户的登录/密码作为表单数据传递。
优势:简单
因此,从实施者的角度来看,我认为OAuth 2的主要优点在于减少了复杂性。它不需要请求签名过程,这并不是非常困难,但确实很琐碎。它大大减少了作为服务客户端所需的工作量,在现代移动世界中,您最想要减少痛苦的地方就是这里。服务器->内容提供者端的减少复杂性使其在数据中心中更具可扩展性。
它将OAuth 1.0a的某些扩展(如xAuth)编码到标准中,这些扩展现在已被广泛使用。

30
关于术语:最好使用受影响方的官方名称(授权服务器,资源服务器,资源所有者),而不是使用不清晰的名称(客户端,服务器,用户...)。 - Aydin K.
10
如果有人不理解OAuth,用OAuth术语而不是简单英语来解释OAuth似乎并不太有效。 - Jay

10
首先,正如OAuth身份验证中清楚指出的那样,OAuth 2.0不是身份验证协议。
在用户访问应用程序的上下文中进行身份验证会告诉应用程序当前用户是谁以及他们是否存在。完整的身份验证协议还可能告诉您关于此用户的许多属性,例如唯一标识符、电子邮件地址以及应用程序说“早上好”时应该称呼他们的方式。
然而,OAuth并没有告诉应用程序任何有关用户的信息。OAuth绝对不会涉及用户,也不会说明用户如何证明其存在或者他们是否仍然存在。就OAuth客户端而言,它请求了一个令牌,得到了一个令牌,并最终使用该令牌来访问某些API。它不知道任何关于谁授权应用程序或者是否有用户存在的信息。
有一个使用OAuth进行用户身份验证的标准:OpenID Connect,与OAuth2兼容。
OpenID Connect ID Token是一个签名的JSON Web Token(JWT),与常规OAuth访问令牌一起提供给客户端应用程序。ID Token包含有关身份验证会话的一组声明,包括用户的标识符(sub)、发出令牌的身份提供者的标识符(iss)以及创建此令牌的客户端的标识符(aud)。
在Go中,您可以查看coreos/dex,这是一个可插拔连接器的OpenID Connect身份(OIDC)和OAuth 2.0提供程序。
本文翻译自vonc

4
如果您正在构建一个应用程序,并且除了您自己之外没有其他客户端,那么实现OAuth是否明智?还是最好坚持直接使用HTTP基本身份验证,完全避免OAuth? - CristianHG

9

我会稍微不同地回答这个问题,并且我将非常精确和简洁,主要是因为 @Peter T 已经回答了全部。

我认为这个标准的主要收益在于遵守两个原则:

  1. 关注点分离。
  2. 授权与通常服务业务的 Web 应用程序解耦。

这样做的好处有:

  1. 您可以实现 Single SignOn 的替代方案:如果您有多个应用程序信任一个 STS。我的意思是,所有应用程序使用一组凭据。
  2. 您可以使您的 Web 应用程序(客户端)访问属于您而不属于 Web 应用程序(客户端)的资源。
  3. 您可以将授权过程委托给您信任的第三方,并永远不必担心用户身份验证。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接