OAuth教程--OAuth 1和2之间的差异

Author Avatar
Sean Yu 7月 13, 2018
  • 在其它设备中阅读本文章

本文是oauth.com上的教程的翻译。(原文地址

OAuth 2.0从头开始就完全重写了OAuth 1.0,仅共享总体目标和一般用户体验。OAuth 2.0不向后兼容OAuth 1.0或1.1,应该被视为一个全新的协议。

OAuth 1.0主要基于两个现有的专有协议:Flickr的授权API和Google的AuthSub。OAuth 1.0的工作是基于当时实际实施经验的最佳解决方案。在许多公司构建OAuth 1 API的过程中,以及许多编写代码来使用API​​的开发人员和社区了解到协议在哪些方面对人们产生了挑战。几个特定领域被确定为需要改进,因为它们要么限制API的能力,要么实施起来太具挑战性。

OAuth 2.0代表了多家公司和个人之间多年的讨论,包括Yahoo!,Facebook,Salesforce,Microsoft,Twitter,Deutsche Telekom,Intuit,Mozilla和Google。

本节介绍OAuth 1.0和2.0之间的主要差异,以及它们背后的动机。如果您熟悉OAuth 1.0,这是快速了解OAuth 2.0中主要更改的良好起点。

术语和角色

OAuth 2.0定义了四个角色(客户端,授权服务器,资源服务器和资源所有者),OAuth 1对这些角色使用不同的术语集。OAuth 2.0的“客户端”被称为“消费者”,“资源所有者”被简称为“用户”,“资源服务器”被称为“服务提供者”。OAuth 1也未明确区分资源服务器和授权服务器的角色。

“two-legged”和“three-legged”这两个术语已被授权类型的概念所取代,例如客户凭证授权类型和授权码授权类型。

身份验证和签名

由于协议的加密要求,大多数OAuth 1.0实施尝试都失败了。对于任何来自简单用户名/密码身份验证的人来说,OAuth 1.0签名的复杂性是一个主要的痛点。

过去,开发人员只需使用用户名和密码即可快速编写Twitter脚本以执行有用的操作。随着迁移到OAuth 1.0,这些开发人员被迫查找,安装和配置库,以便向Twitter API发出请求,因为它需要对每个请求进行加密签名。

随着OAuth 2.0承载令牌的引入,再次可以通过cURL命令快速进行API调用。使用访问令牌而不是使用用户名和密码。

例如,在OAuth之前,您可能已经看过API文档中的示例,例如:

curl --user bob:pa55 https://api.example.com/profile

使用OAuth 1 API,不再可能对此类示例进行硬编码,因为请求必须使用应用程序的密钥进行签名。Twitter等一些服务开始在其开发者网站中提供“签名生成器”工具,这样您就可以在不使用库的情况下从网站生成curl命令。例如,Twitter上的工具生成一个curl命令,例如:

curl --get 'https://api.twitter.com/1.1/statuses/show.json' \
--data 'id=210462857140252672' \
--header 'Authorization: OAuth oauth_consumer_key="xRhHSKcKLl9VF7fbyP2eEw", oauth_nonce="33ec5af28add281c63db55d1839d90f1", oauth_signature="oBO19fJO8imCAMvRxmQJsA6idXk%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1471026075", oauth_token="12341234-ZgJYZOh5Z3ldYXH2sm5voEs0pPXOPv8vC0mFjMFtG", oauth_version="1.0"'

使用OAuth 2.0承载令牌,请求中只需要令牌本身,因此示例再次变得非常简单:

curl https://api.example.com/profile -H "Authorization: Bearer XXXXXXXXXXX"

这在API的易用性和良好的安全实践之间提供了良好的平衡。

用户体验和备用令牌颁发选项

OAuth 2.0有两个主要部分:用户获取授权(最终结果是应用程序具有该用户的访问令牌),并使用访问令牌代表用户发出请求。获取访问令牌的方法称为流程。

OAuth 1.0最初有3个流程,适用于基于Web的应用程序,桌面客户端以及移动或“有限”设备。但是,随着规范的发展,这三个流程合并为一个理论上支持所有三种客户端类型的流程。在实践中,流程适用于基于Web的应用程序,但在其他地方提供了较差的体验。

随着越来越多的网站开始使用OAuth,尤其是Twitter,开发人员意识到OAuth提供的单一流程非常有限,并且通常会产生糟糕的用户体验。另一方面,Facebook Connect提供了更丰富的流程,适用于Web应用程序,移动设备和游戏控制台。

OAuth 2.0通过再次定义多个流程来解决这个问题,称为“授权类型”,可以灵活地支持各种应用程序类型。还有一种机制来开发扩展来处理以前没想过的用例。

服务器端应用程序使用“授权码”授权类型和客户端秘钥,提示用户授权应用程序,并生成一个授权码,该代码将传回应用程序。然后,应用程序的服务器用授权码交换访问令牌。服务器端应用程序使用其秘钥来和授权码交换访问令牌,可以获得此流程的安全性。

单页或移动应用程序使用相同的授权类型,但不使用客户机秘钥。相反,安全性在于验证重定向URL以及可选的PKCE扩展。

OAuth 2.0正式定义了“密码”授权类型,允许应用程序收集用户的用户名和密码,并将其交换为访问令牌。虽然这是规范的一部分,但它仅供受信任的客户端使用,例如服务自己的第一方应用程序。它不应该被第三方应用程序使用,因为这将允许第三方应用程序访问用户的用户名和密码。

当应用程序访问其自己的资源时,将使用“客户端凭据”授予。此授权类型只是交换client_idclient_secret来获取访问令牌。

OAuth 2.0还支持扩展授予类型,允许组织定义自己的自定义授权类型以支持其他客户端类型或在OAuth与现有系统之间提供桥接。

其中一个扩展是用于在没有Web浏览器的设备上授权应用程序的设备流程。

规模表现

随着较大的提供商开始使用OAuth 1.0,社区意识到该协议有一些限制,使得难以扩展到大型系统。OAuth 1.0需要跨不同步骤进行状态管理,并且通常跨不同服务器进行。它需要生成临时凭证,这些凭证通常被丢弃未使用,并且通常需要发布安全性较低且难以管理的持久凭证。

此外,OAuth 1.0要求受保护资源endpoint可以访问客户端凭据以验证请求。这打破了大多数大型提供商的典型架构,其中集中授权服务器用于颁发凭证,并且单独的服务器用于处理API调用。由于OAuth 1.0需要使用客户端凭据来验证签名,因此这种分离非常困难。

OAuth 2.0仅在应用程序从用户获取授权时使用客户端凭据来解决此问题。在授权步骤中使用凭据后,在进行API调用时仅使用生成的访问令牌。这意味着API服务器不需要知道客户端凭据,因为它们可以自己验证访问令牌。

承载令牌(Bearer Tokens)

在OAuth 1中,访问令牌有两个组件,即公共字符串和私有字符串。签名请求时使用私有字符串,并且从不通过网络发送。

访问OAuth 2.0 API的最常用方法是使用“承载令牌”。这是一个单个字符串,用作API请求的身份验证,在HTTP“授权”header中发送。该字符串对于使用它的客户来说毫无意义,并且可能具有不同的长度。

承载令牌是一种更简单的API请求方式,因为它们不需要对每个请求进行加密签名。权衡是所有API请求必须通过HTTPS连接进行,因为请求包含一个明文标记,如果被截获,任何人都可以使用该标记。优点是它不需要复杂的库来发出请求,并且客户端和服务器实现起来要简单得多。

承载令牌的缺点是没有任何东西阻止其他应用程序使用Bearer令牌,如果这个应用程序可以访问它。这是对OAuth 2.0的常见批评,尽管大多数提供商仍然只使用Bearer令牌。在正常情况下,当应用程序正确保护其控制下的访问令牌时,这不是问题,尽管从技术上讲它不太安全。如果您的服务需要更安全的方法,则可以使用可满足安全要求的其他访问令牌类型。

具有长期授权的短期令牌

OAuth 1.0 API通常会发布极其持久的访问令牌。这些令牌可以无限期地持续,或者大约一年。虽然对开发人员来说很方便,但在某些情况下,这证明限制了一些服务。

负责任的API提供商应允许用户查看他们已授权使用其帐户的第三方应用,并且应该能够根据需要撤消应用。如果用户撤消了应用,则API应该停止尽快结束发布到该应用的访问令牌。根据API的实现方式,这可能具有挑战性,或者需要系统内部部件之间的其他联系。

使用OAuth 2.0,授权服务器可以发出短期访问令牌和长期刷新令牌。这允许应用程序在不涉及用户的情况下获得新的访问令牌,但也增加了服务器更容易撤销令牌的能力。此功能是从Yahoo!的BBAuth协议和后来的OAuth 1.0会话扩展中采用的。

角色分离

OAuth 2.0的设计决策之一是明确地将授权服务器的角色与API服务器分开。这意味着您可以将授权服务器构建为独立组件,该组件仅负责从用户获取授权并向客户端发送令牌。这两个角色可以位于物理上独立的服务器上,甚至可以位于不同的域名上,从而允许系统的每个部分独立扩展。某些提供程序有许多资源服务器,每个服务器位于不同的子域中。

授权服务器需要了解应用程序的client_idclient_secret,但API服务器将只需要接受访问令牌。通过将授权服务器构建为独立组件,您可以避免与API服务器共享数据库,从而可以更轻松地独立于授权服务器扩展API服务器,因为它们不需要共享公共数据存储。

例如,Google的OAuth 2.0实施使用“accounts.google.com”上的服务器进行授权请求,但在向Google+ API发出请求时使用“www.gooogleapis.com”。

服务提供商的好处是这些系统的开发可以完全独立地由不同的团队和不同的时间线发生。由于它们是完全独立的,因此可以独立扩展,升级或更换,而无需考虑系统的其他部分。