背景:我已经为OAuth 1.0a和2.0编写了客户端和服务器堆栈。
OAuth 1.0a和2.0都支持双向身份验证,其中服务器可以确保用户的身份,以及三方身份验证,其中内容提供者向服务器保证用户的身份。三方身份验证是授权请求和访问令牌发挥作用的地方,需要注意的是OAuth 1也有这些功能。
复杂的三方身份验证
OAuth规范的一个主要点是,内容提供者(例如Facebook、Twitter等)向服务器(例如希望代表客户端与内容提供者通信的Web应用程序)保证客户端具有某些身份。三方身份验证所提供的功能是在不需要客户端或服务器了解该身份的详细信息(例如用户名和密码)的情况下完成此操作。
不过,不深入讨论OAuth的细节:
- 客户端向服务器提交授权请求,服务器验证其是否是其服务的合法客户端。
- 服务器将客户端重定向到内容提供者,请求访问其资源。
- 内容提供者验证用户的身份,并经常请求其访问资源的权限。
- 内容提供者将客户端重定向回服务器,通知其成功或失败。此请求在成功时包括授权代码。
- 服务器对内容提供者进行一次带外请求,并用授权代码交换访问令牌。
服务器现在可以通过传递访问令牌代表用户向内容提供者发出请求。
每次交换(客户端->服务器,服务器->内容提供者)都包括共享密钥的验证,但由于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)编码到标准中,这些扩展现在已被广泛使用。