背景:我为 OAuth 1.0a 和 2.0 编写了客户端和服务器堆栈。
OAuth 1.0a 和 2.0 都支持 双腿身份验证,其中服务器可以确保用户的身份,以及 三腿身份验证,其中服务器可以确保由用户身份的内容提供者提供。三足身份验证是授权请求和访问令牌发挥作用的地方,重要的是要注意 OAuth 1 也有这些。
复杂的一:三足认证
OAuth 规范的一个要点是内容提供者(例如 Facebook、Twitter 等)确保 服务器(例如希望代表客户与内容提供者交谈)客户具有某种身份。三足身份验证提供的功能是无需客户端或服务器知道该身份的详细信息(例如用户名和密码)即可做到这一点。
不用 (?) 深入了解 OAuth 的细节:
- 客户端向服务器提交授权请求,服务器验证客户端是其服务的合法客户端。
- 服务器将客户端重定向到内容提供者以请求访问其资源。
- 内容提供商验证用户的身份,并经常请求他们访问资源的权限。
- 内容提供者将客户端重定向回服务器,通知它成功或失败。此请求包含一个成功的授权代码。
- 服务器向内容提供者发出带外请求,并用授权码交换访问令牌。
服务器现在可以通过传递访问令牌代表用户向内容提供者发出请求。
每个交换(客户端->服务器、服务器->内容提供者)都包括对共享密钥的验证,但由于 OAuth 1 可以在未加密的连接上运行,因此每次验证都无法通过网络传递密钥。
正如您所指出的,使用 HMAC 已经完成了。客户端使用它与服务器共享的秘密来签署其授权请求的参数。服务器接受参数,使用客户端的密钥对其进行签名,并且能够查看它是否是合法的客户端(在上面的步骤 1 中)。
此签名要求客户端和服务器就参数的顺序达成一致(因此它们签署完全相同的字符串),关于 OAuth 1 的主要抱怨之一是它需要服务器和客户端排序和签名相同。这是繁琐的代码,要么是正确的,要么你得到401 Unauthorized 几乎没有帮助。这增加了编写客户端的障碍。
通过要求授权请求通过 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 中将其视为 Resource Owner Password Credentials。
基本上,如果您可以使用用户的凭据(用户名和密码)信任客户端,他们可以直接与内容提供商交换这些凭据以获得访问令牌。这使得 OAuth 在移动应用程序上更加有用 - 使用三足身份验证,您必须嵌入 HTTP 视图才能处理内容服务器的授权过程。
对于 OAuth 1,这不是官方标准的一部分,并且需要与所有其他请求相同的签名过程。
我刚刚使用资源所有者密码凭据实现了 OAuth 2 的服务器端,从客户端的角度来看,获取访问令牌变得很简单:从服务器请求访问令牌,将客户端 id/secret 作为 HTTP 授权传递标题和用户的登录名/密码作为表单数据。
优点:简单
因此,从实施者的角度来看,我在 OAuth 2 中看到的主要优势在于降低了复杂性。它不需要请求签名程序,这并不困难,但肯定很繁琐。它极大地减少了充当服务客户端所需的工作,这是(在现代移动世界中)您最希望最大程度地减少痛苦的地方。服务器->内容提供者端复杂性降低,使其在数据中心更具可扩展性。
并且它将一些现在广泛使用的 OAuth 1.0a 扩展(如 xAuth)编入标准。