Skip to main content

1. 简介 (Introduction)

快速总结

1. 背景

OAuth 2.0 是一个授权框架 (Authorization Framework),允许第三方应用在用户授权下访问其账户资源,而无需共享凭据 (Credentials)。

2. 客户端类型 (Client Types)

  • Web应用 (Web Application): 运行在服务器上的应用,如PHP、Python、Ruby、Java应用。
  • 用户代理应用 (User-Agent-Based Application): 在用户设备上通过用户代理 (如浏览器) 执行的应用。
  • 原生应用 (Native Application): 在用户设备上直接执行的应用,如桌面应用或移动应用。

3. 授权类型 (Grant Types)

  • 授权码 (Authorization Code): 用于获取访问令牌 (Access Token) 和刷新令牌 (Refresh Token)。
  • 隐式许可 (Implicit Grant): 用于获取访问令牌。
  • 资源所有者密码凭据 (Resource Owner Password Credentials): 用于获取访问令牌和刷新令牌。
  • 客户端凭据 (Client Credentials): 用于获取访问令牌。

4. 令牌端点 (Token Endpoint)

客户端使用此端点从授权服务器 (Authorization Server) 请求访问令牌。

5. 刷新令牌 (Refresh Token)

用于获取新的访问令牌,无需再次进行用户授权。

6. 错误响应 (Error Response)

如果请求失败,授权服务器会返回错误响应。

7. 扩展性 (Extensibility)

OAuth 2.0设计为可扩展,允许开发者定义新的授权类型和令牌类型。

OAuth 2.0 简介

在传统的客户端-服务器身份验证模式中,客户端 (Client) 请求服务器上受限访问的资源 (受保护资源, Protected Resource) 时,需要使用资源所有者 (Resource Owner) 的凭据进行身份验证。资源所有者为了让第三方应用访问受限资源,需要与第三方共享其凭据。这会造成以下问题和局限:

  • 第三方应用需要存储资源所有者的凭据供将来使用,通常是明文密码。
  • 服务器需要支持密码身份认证,尽管密码认证存在固有的安全缺陷。
  • 第三方应用获得的受保护资源访问权限过于宽泛,导致资源所有者失去对资源使用时限或使用范围的控制。
  • 资源所有者无法仅撤销某个第三方的访问权限而不影响其他方,并且只能通过更改密码来撤销第三方的访问权限。
  • 任何第三方应用的安全妥协都会导致终端用户的密码及该密码保护的所有数据被泄露。

OAuth通过引入授权层 (Authorization Layer) 并分离客户端角色和资源所有者角色来解决这些问题。在OAuth中,客户端在请求访问由资源所有者控制并托管在资源服务器 (Resource Server) 上的资源时,会被颁发一组不同于资源所有者凭据的凭据。

客户端获得访问令牌 (Access Token) ——一个代表特定作用域 (Scope)、生命期以及其他访问属性的字符串,用于代替资源所有者的凭据来访问受保护资源。访问令牌由授权服务器 (Authorization Server) 在资源所有者认可的情况下颁发给第三方客户端。客户端使用访问令牌访问托管在资源服务器上的受保护资源。

示例: 终端用户 (资源所有者) 可以授权一个打印服务 (客户端) 访问她存储在图片分享网站 (资源服务器) 上的受保护图片,而无需与打印服务分享自己的用户名和密码。相反,她直接与图片分享网站信任的服务器 (授权服务器) 进行身份验证,该服务器向打印服务颁发特定的委托凭据 (访问令牌)。

本规范是为 HTTP(RFC2616)协议量身定制。在任何非 HTTP 协议上使用 OAuth 不在本规范的范围之内。

OAuth 1.0 协议(RFC5849)作为一个指导性文档发布,是一个小社区的工作成果。本标准化规范在 OAuth 1.0 的部署经验之上构建,也包括其他使用案例以及从更广泛的 IETF 社区收集到的可扩展性需求。

OAuth 2.0 协议不向后兼容 OAuth 1.0。这两个版本可以在网络上共存,实现者可以选择同时支持他们。然而,本规范的用意是新的实现支持按本文档指定的 OAuth 2.0,OAuth 1.0 仅用于支持现有的部署。

OAuth 2.0 协议与 OAuth 1.0 协议实现细节没有太多关联。熟悉 OAuth 1.0 的实现者应该学习本文档,而不对有关 OAuth 2.0 的结构和细节做任何假设。

1.1 角色 (Roles)

OAuth定义了四种角色:

  1. 资源所有者 (Resource Owner)
    能够授予受保护资源访问权限的实体。当资源所有者是个人时,称为最终用户 (End-User)。

  2. 资源服务器 (Resource Server)
    托管受保护资源的服务器,能够接收和响应使用访问令牌对受保护资源的请求。

  3. 客户端 (Client)
    代表资源所有者并经其授权发起对受保护资源请求的应用程序。术语"客户端"并非特指任何特定的实现特点 (例如: 应用程序是否在服务器、桌面或其他设备上执行)。

  4. 授权服务器 (Authorization Server)
    在成功验证资源所有者并获得授权后,向客户端颁发访问令牌的服务器。授权服务器和资源服务器之间的交互超出了本规范的范围。授权服务器可以与资源服务器是同一台服务器,也可以是独立的实体。一个授权服务器可以颁发被多个资源服务器接受的访问令牌。

1.2. 协议流程


+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+

图 1:抽象的协议流程

图 1 中所示的抽象 OAuth 2.0 流程描述了四个角色之间的交互,包括以下步骤:

  • (A)客户端向资源所有者请求授权。授权请求可以直接向资源所有者发起,或者更可取的是通过作为中介的授权服务器间接发起。
  • (B)客户端收到授权许可,这是一个代表资源所有者的授权的凭据,使用本规范中定义的四种许可类型之一或者使用扩展许可类型表示。授权许可类型取决于客户端请求授权所使用的方式以及授权服务器支持的类型。
  • (C)客户端与授权服务器进行身份认证并出示授权许可请求访问令牌。
  • (D)授权服务器验证客户端身份并验证授权许可,若有效则颁发访问令牌。
  • (E)客户端从资源服务器请求受保护资源并出示访问令牌进行身份验证。
  • (F)资源服务器验证访问令牌,若有效则满足该请求。

客户端用于从资源所有者获得授权许可(步骤(A)和(B)所示)的更好方法是使用授权服务器作为中介,如 4.1 节图 3 所示。

1.3. 授权许可

1.3.1. 授权码

授权码通过使用授权服务器做为客户端与资源所有者的中介而获得。客户端不是直接从资源所有者请求授权,而是引导资源所有者至授权服务器(由在 RFC2616 中定义的用户代理),授权服务器之后引导资源所有者带着授权码回到客户端。

在引导资源所有者携带授权码返回客户端前,授权服务器会鉴定资源所有者身份并获得其授权。由于资源所有者只与授权服务器进行身份验证,所以资源所有者的凭据不需要与客户端分享。

1.3.2. 隐式许可

隐式许可是为用如 JavaScript 等脚本语言在浏览器中实现的客户端而优化的一种简化的授权码流程。在隐式许可流程中,不再给客户端颁发授权码,取而代之的是客户端直接被颁发一个访问令牌(作为资源所有者的授权)。这种许可类型是隐式的,因为没有中间凭据(如授权码)被颁发(之后用于获取访问令牌)。

当在隐式许可流程中颁发访问令牌时,发授权服务器不对客户端进行身份验证。在某些情况下,客户端身份可以通过用于向客户端传送访问令牌的重定向 URI 验证。访问令牌可能会暴露给资源所有者,或者对资源所有者的用户代理有访问权限的其他应用程序。

1.3.3. 资源所有者密码凭据

资源所有者密码凭据(即用户名和密码),可以直接作为获取访问令牌的授权许可。这种凭据只能应该当资源所有者和客户端之间具有高度信任时(例如,客户端是设备的操作系统的一部分,或者是一个高度特权应用程序),以及当其他授权许可类型(例如授权码)不可用时被使用。

尽管本授权类型需要对资源所有者凭据直接的客户端访问权限,但资源所有者凭据仅被用于一次请求并被交换为访问令牌。通过凭据和长期有效的访问令牌或刷新令牌的互换,这种许可类型可以消除客户端存储资源所有者凭据供将来使用的需要。

1.3.4. 客户端凭据

当授权范围限于客户端控制下的受保护资源或事先与授权服务器商定的受保护资源时客户端凭据可以被用作为一种授权许可。典型的当客户端代表自己表演(客户端也是资源所有者)或者基于与授权服务器事先商定的授权请求对受保护资源的访问权限时,客户端凭据被用作为授权许可。

1.4. 访问令牌

访问令牌是用于访问受保护资源的凭据。访问令牌是一个代表向客户端颁发的授权的字符串。该字符串通常对于客户端是不透明的。令牌代表了访问权限的由资源所有者许可并由资源服务器和授权服务器实施的具体范围和期限。

令牌可以表示一个用于检索授权信息的标识符或者可以以可验证的方式自包含授权信息(即令牌字符串由数据和签名组成)。额外的身份验证凭据——

1.5. 刷新令牌

刷新令牌是用于获取访问令牌的凭据。刷新令牌由授权服务器颁发给客户端,用于在当前访问令牌失效或过期时,获取一个新的访问令牌,或者获得相等或更窄范围的额外的访问令牌(访问令牌可能具有比资源所有者所授权的更短的生命周期和更少的权限)。颁发刷新令牌是可选的,由授权服务器决定。如果授权服务器颁发刷新令牌,在颁发访问令牌时它被包含在内(即图 1 中的步骤 D)。

刷新令牌是一个代表由资源所有者给客户端许可的授权的字符串。该字符串通常对于客户端是不透明的。该令牌表示一个用于检索授权信息的标识符。不同于访问令牌,刷新令牌设计只与授权服务器使用,并不会发送到资源服务器。

图 2 中的所示流程包含以下步骤:

  • (A)客户端通过与授权服务器进行身份验证并出示授权许可请求访问令牌。
  • (B)授权服务器对客户端进行身份验证并验证授权许可,若有效则颁发访问令牌和刷新令牌。
  • (C)客户端通过出示访问令牌向资源服务器发起受保护资源的请求。
  • (D)资源服务器验证访问令牌,若有效则满足该要求。
  • (E)步骤(C)和(D)重复进行,直到访问令牌到期。如果客户端知道访问令牌已过期,跳到步骤 (G),否则它将继续发起另一个对受保护资源的请求。
  • (F)由于访问令牌是无效的,资源服务器返回无效令牌错误。
  • (G)客户端通过与授权服务器进行身份验证并出示刷新令牌,请求一个新的访问令牌。客户端身份 验证要求基于客户端的类型和授权服务器的策略。
  • (H)授权服务器对客户端进行身份验证并验证刷新令牌,若有效则颁发一个新的访问令牌(和—— 可选地——一个新的刷新令牌)。
+--------+                                           +---------------+
| |--(A)------- Authorization Grant --------->| |
| | | |
| |<-(B)----------- Access Token -------------| |
| | & Refresh Token | |
| | | |
| | +----------+ | |
| |--(C)---- Access Token ---->| | | |
| | | | | |
| |<-(D)- Protected Resource --| Resource | | Authorization |
| Client | | Server | | Server |
| |--(E)---- Access Token ---->| | | |
| | | | | |
| |<-(F)- Invalid Token Error -| | | |
| | +----------+ | |
| | | |
| |--(G)----------- Refresh Token ----------->| |
| | | |
| |<-(H)----------- Access Token -------------| |
+--------+ & Optional Refresh Token +---------------+

1.6. TLS版本

本规范任何时候使用传输层安全性(TLS),基于广泛的部署和已知的安全漏洞TLS的相应版本(或多个版本)将会随时间而变化。在本规范撰写时,TLS 1.2版[RFC5246][RFC5246]是最新的版本,但它具有非常局限的部署基础,可能还未准备好可以实现。TLS 1.0版[RFC2246][RFC2246] 是部署最广泛的版本并将提供最宽泛的互操作性。

实现也可以支持满足其安全需求的其他传输层安全机制。

1.7. HTTP重定向

本规范广泛采用了HTTP重定向,有此客户端或授权服务器引导资源所有者的用户代理到另一个目的地址。虽然本规范中的例子演示了HTTP 302状态码的使用,但是任何其他通过用户代理完成重定向的方法都是允许的并被考虑作为实现细节。

1.8. 互操作性

OAuth 2.0提供了丰富的具有明确的安全性质的授权框架。然而,尽管在其自身看来是一个带有许多可选择组件的丰富且高度可扩展的框架,本规范有可能产生许多非可互操作的实现。

此外,本规范中留下一些必需组件部分或完全没有定义(例如,客户端注册、授权服务器性能、端点发现等)。没有这些组件,客户端必须针对特定的授权服务器和资源服务器被手动并专门配置,以进行互操作。

本框架设计具有一个明确的期望,即未来工作将定义实现完整的web范围的互操作性所需的规范性的配置和扩展。

1.9. 符号约定

本规范中的关键词“必须”、“不能”、“必需的”、“要”、“不要”、“应该”、“不应该”、“推荐的”、“可以”以及“可选的”按[RFC2119][RFC2119]所述解释。 本规范使用[RFC5234][RFC5234]的扩展巴科斯-诺尔范式(ABNF)表示法。此外,来自“统一资源标识符(URI):通用语法”[RFC3986][RFC3986] 的规则URI引用也包含在内。

某些安全相关的术语按照[RFC4949][RFC4949] 中定义的意思理解。这些术语包括但不限于:“攻击”、“身份认证”、“授权”、“证书”、“机密”,“凭据”,“加密”,“身份”,“记号”,“签名”,“信任”,“验证”和“核实”。

除非另有说明,所有协议参数的名称和值是大小写敏感的。

[RFC2119]: "Key words for use in RFCs to Indicate Requirement Levels"

  • 描述了一组关键词,用于指示RFC文档中的要求级别,例如,"MUST," "SHOULD," "MAY" 等。这有助于标准化文档中的规定程度。

[RFC5234]: "Augmented BNF for Syntax Specifications: ABNF"

  • 定义了扩展的巴科斯-尼科尔斯范式(ABNF),这是一种用于定义互联网协议消息语法的标准表示方法。它在许多协议规范中广泛使用。

[RFC3986]: "Uniform Resource Identifier (URI): Generic Syntax"

  • 规定了统一资源标识符(URI)的通用语法,包括URL(统一资源定位符)和URN(统一资源名称)。这是在互联网上定位和标识资源的关键标准。

[RFC4949]: "Internet Security Glossary, Version 2"

  • 提供了互联网安全领域的术语和定义的详细字典。它有助于确保在安全协议和实践中使用一致的术语和概念。