UP | HOME

OAuth 2.0 应用授权协议

Table of Contents

1 OAuth 2.0 协议

RFC 5849 文档中定义了 OAuth 1.0 认证协议,OAuth 2.0 是 OAuth 协议的延续版本, 但不向前兼容 OAuth 2.0(即完全废止了 OAuth1.0)。 OAuth 2.0 关注客户端开发者的简 易性。要么通过组织在资源拥有者和 HTTP 服务商之间的被批准的交互动作代表用户,要 么允许第三方应用代表用户获得访问的权限。同时为 Web 应用,桌面应用和手机,和起 居室设备提供专门的认证流程。2012 年 10 月,OAuth 2.0 协议正式发布为 RFC 6749

2 介绍

2.1 角色

OAuth 定义了如下四个角色:

  • Resource Owner: 资源所有者,能够许可对受保护资源的访问权限的实体。当资源所有 者是个人时,它被称为最终用户
  • Resource Server: 资源服务器,托管受保护资源的服务器,能够接收和响应使用访问 令牌对受保护资源的请求
  • Client: 客户端,通常是三方应用。使用资源所有者的授权代表资源所有者发起对受 保护资源的请求的应用程序。术语 "客户端" 并非特指任何特定的的实现特点(例如: 应用程序是否是在服务器、台式机或其他设备上执行)
  • Authorization Server: 授权服务器,在成功验证资源所有者且获得授权后颁发访问 令牌给客户端的服务器

2.2 协议流程及授权方式

协议的流程如下图所示

oauth-abstract-protocol-flow.png

  1. 客户端从资源所有者处请求授权。授权请求可以直接向资源所有者发起(如图所示), 或者更可取的是通过授权服务器作为中介间接发起。
  2. 客户端收到授权许可,这是一个代表资源所有者的授权的凭据,使用本规范中定义的 四种许可类型之一或者使用扩展许可类型表示。授权许可类型取决于客户端请求授权 所使用的方法以及授权服务器支持的类型。
  3. 客户端与授权服务器进行身份认证并出示授权许可以请求 Access Token 。
  4. 授权服务器验证客户端身份并验证授权许可,若有效则颁发 Access Token 。
  5. 客户端从资源服务器请求受保护资源并出示 Access Token 进行身份验证。
  6. 资源服务器验证 Access Token ,若有效则处理该请求。

客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。 OAuth 2.0 定义了四种授权方式

  • 授权码许可(authorization code)
  • 简化许可(implicit)
  • 密码许可(resource owner password credentials)
  • 客户端许可(client credentials)

2.3 Access Token

Access Token 即访问令牌,Access Token 是用来包含资源的,客户端在访问资源是必 须携带 Access Token 才能正确获取到相应的资源

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

2.4 Refresh Token 及刷新过程

Refresh Token 即刷新令牌。如果用户访问的时候,客户端的 Access Token 已经过期, 则需要使用 Reresh Token 申请一个新的 Access Token 。刷新 Access Token 的流程 如下图

oauth-refreshing-expired-access-token.png

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

  1. 客户端通过与授权服务器进行身份验证并出示授权许可请求 Access Token
  2. 授权服务器对客户端进行身份验证并验证授权许可,若有效则颁发 Access Token 和 刷新令牌
  3. 客户端通过出示 Access Token 向资源服务器发起受保护资源的请求
  4. 资源服务器验证 Access Token ,若有效则满足该要求
  5. 步骤 3步骤 4 重复进行,直到 Access Token 到期。如果客户端知道 Access Token 已过期,跳到 步骤 7 ,否 则它将继续发起另一个对受保护资源的 请求
  6. 由于 Access Token 是无效的,资源服务器返回无效令牌错误。
  7. 客户端通过与授权服务器进行身份验证并出示 Refresh Token,请求一个新的 Access Token 。客户端身份验证要求基于客户端的类型和授权服务器的策略
  8. 授权服务器对客户端进行身份验证并验证 Refresh Token,若有效则颁发一个新的 Access Token (和可选地一个新的 Refresh Token)

3 授权许可模式

3.1 授权码许可

3.1.1 授权码许可流程

授权码许可类型用于获得 Access Token 和 Refresh Token 并且为受信任的客户端进 行了优化。由于这是一个基于重定向的流程,客户端必须能够与资源所有者的 User Agent(用户代理,通常是 Web 浏览器)进行交互并能够接收来自授权服务器的传入请 求(通过重定向)

oauth-authorization-code-flow.png

在图中所示的流程包括以下步骤:

  1. 客户端通过向授权端点引导资源所有者的用户代理开始流程。客户端包括它的客户 端标识、请求范围、本地状态和重定向 URI,一旦访问被许可(或拒绝)授权服务 器将传送用户代理回到该 URI
  2. 授权服务器验证资源拥有者的身份(通过用户代理),并确定资源所有者是否授予 或拒绝客户端的访问请求
  3. 假设资源所有者许可访问,授权服务器使用之前(在请求时或客户端注册时)提供 的重定向 URI 重定向用户代理回到客户端。重定向 URI 包括授权码和之前客户端 提供的任何本地状态
  4. 客户端通过包含上一步中收到的授权码从授权服务器的令牌端点请求 Access Token 。当发起请求时,客户端与授权服务器进行身份验证。客户端包含用于获得授权码 的重定向 URI 来用于验证。
  5. 授权服务器对客户端进行身份验证,验证授权代码,并确保接收的重定向 URI 与所 在的 步骤 3 中用于重定向(资源所有者的用户代理)到客户端的 URI 相匹配。 如果通过,授权服务器响应返回 Access Token 与可选的 Refresh Token。

3.1.2 授权码许可请求

请求参数的客户端使用 application/x-www-form-urlencoded 格式向授权端点 URI 的查询部分添加下列参数构造请求 URI:

  • response_type 必需的。值必须被设置为 "code"
  • client_id 必需的。客户端标识
  • redirect_uri 可选的
  • scope 可选的。访问请求的范围
  • state 推荐的。客户度用于维护请求和回调之间的状态的不透明的值。当重定向用 户代理回到客户端时,授权服务器包含此值。该参数应该用于防止跨站点请求伪造

客户端使用 HTTP 重定向响应向构造的 URI 定向资源所有者,或者通过经由用户代理 至该 URI 的其他可用方法。 例如,客户端使用 TLS 定向用户代理发起下述 HTTP 请求 (额外的换行仅用于显示目的):

GET /authorize?response_type=code&client_id=s16BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

授权服务器验证该请求,确保所有需要的参数已提交且有效。如果请求是有效的,授权 服务器对资源所有者进行身份验证并获得授权决定(通过询问资源所有者或通过经由其 他方式确定批准)。

当确定决定后,授权服务器使用 HTTP 重定向响应向提供的客户端重定向 URI 定向用 户代理,或者通过经由用户代理至该 URI 的其他可行方法。

3.1.3 授权码许可响应

  • code 必需的。授权服务器生成的授权码。授权码必须在颁发后很快过期以减小泄 露风险。推荐的最长的授权码生命周期是 10 分钟。客户端不能使用授权码超过一次。 如果一个授权码被使用一次以上,授权服务器必须拒绝该请求并应该撤销(如可能) 先前发出的基于该授权码的所有令牌。授权码与客户端标识和重定向 URI 绑定
  • state 必需的,若 state 参数在客户端授权请求中提交。从客户端接收的精确值

3.1.4 Access Token 请求

  • grant_type 必需的。值必须被设置为 "authorizationcode"
  • code 从授权服务器收到的授权码
  • redirect_uri 必需的,若 redirect_uri 参数包含在授权请求中,且他们的值 必须相同。
  • client_id 必需的,如果客户端没有与授权服务器进行身份认证。

3.1.5 Access Token 响应

如果访问令牌请求是有效的且被授权,授权服务器颁发访问令牌以及可选的 Refresh Token。 如果请求客户端身份验证失败或无效,授权服务器返回错误响应。下面是一个样例成功 响应:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter":"example_value"
}

3.2 隐私许可

3.2.1 隐式许可流程

隐式授权类型被用于获取 Access Token(它不支持发行 Refresh Token),并对知道操作具体重定 向 URI 的公共客户端进行优化。这些客户端通常在浏览器中使用诸如 JavaScript 的脚本语言实现。

由于这是一个基于重定向的流程,客户端必须能够与资源所有者的用户代理(通常是 Web 浏览器)进行交互并能够接收来自授权服务器的传入请求(通过重定向)。

不同于客户端分别请求授权和 Access Token 的授权码许可类型,客户端收到 Access Token 作为授 权请求的结果。

隐式许可类型不包含客户端身份验证而依赖于资源所有者在场和重定向 URI 的注册。因为 Access Token 被编码到重定向 URI 中,它可能会暴露给资源所有者和其他驻留在相同设备上的 应用。

oauth-implicit-grant-flow.png

  1. 客户端通过向授权端点引导资源所有者的用户代理开始流程。客户端包括它的客户端 标识、请求范围、本地状态和重定向 URI,一旦访问被许可(或拒绝)授权服务器将传 送用户代理回到该 URI。
  2. 授权服务器验证资源拥有者的身份(通过用户代理),并确定资源所有者是否授予或 拒绝客户端的访问请求。
  3. 假设资源所有者许可访问,授权服务器使用之前(在请求时或客户端注册时)提供的 重定向 URI 重定向用户代理回到客户端。重定向 URI 在 URI 片段中包含 Access Token。
  4. 用户代理顺着重定向指示向 Web 托管的客户端资源发起请求(按 RFC2616 该请求不包含 片段)。用户代理在本地保留片段信息。
  5. Web 托管的客户端资源返回一个网页(通常是带有嵌入式脚本的 HTML 文档),该网页能 够访问包含用户代理保留的片段的完整重定向 URI 并提取包含在片段中的 Access Token(和 其他参数)。
  6. 用户代理在本地执行 Web 托管的客户端资源提供的提取 Access Token 的脚本。
  7. 用户代理传送 Access Token 给客户端。

3.2.2 Access Token 请求

请求参数的客户端使用 application/x-www-form-urlencoded 格式向授权端点 URI 的查询部分添加下列参数构造请求 URI:

  • response_type 必需的。值必须被设置为 "token"
  • client_id 必需的。客户端标识
  • redirect_uri 可选的
  • scope 可选的。访问请求的范围
  • state 推荐的。客户度用于维护请求和回调之间的状态的不透明的值。当重定向用 户代理回到客户端时,授权服务器包含此值。该参数应该用于防止跨站点请求伪造

客户端使用 HTTP 重定向响应向构造的 URI 定向资源所有者,或者通过经由用户代理至该 URI 的其他可用方法。

例如,客户端使用 TLS 定向用户代理发起下述 HTTP 请求(额外的换行仅用于显示目的):

GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

授权服务器验证该请求,确保所有需要的参数已提交且有效。授权服务器必须验证它将 重定向 Access Token 的重定向 URI 与客户端注册的重定向 URI 匹配。

如果请求是有效的,授权服务器对资源所有者进行身份验证并获得授权决定(通过询问 资源所有者或通过经由其他方式确定批准)。

当确定决定后,授权服务器使用 HTTP 重定向响应向提供的客户端重定向 URI 定向用户代 理,或者通过经由用户代理至该 URI 的其他可行方法。

3.2.3 Access Token 响应

  • access_token 必需的。授权服务器颁发的 Access Token。
  • token_type 必需的。颁发的令牌的类型。值是大小写不敏感的。
  • expires_in 推荐的。以秒为单位的 Access Token 生命周期。例如,值“3600”表示访问 令牌将在从生成响应时的 1 小时后到期。如果省略,则授权服务器应该通过其他方式 提供过期时间,或者记录默认值。
  • scope 可选的,若与客户端请求的范围相同;否则,是必需的。如 3.3 节所述的访 问令牌的范围。
  • state 必需的,若“state”参数在客户端授权请求中提交。从客户端接收的精确值。 授权服务器不能颁发 Refresh Token。

3.3 (资源所有者)密码许可

资源所有者密码凭据许可类型适合于资源所有者与客户端具有信任关系的情况,如设备 操作系统或高级特权应用。当启用这种许可类型时授权服务器应该特别关照且只有当其 他流程都不可用时才可以。

这种许可类型适合于能够获得资源所有者凭据(用户名和密码,通常使用交互的形式) 的客户端。通过转换已存储的凭据至 Access Token,它也用于迁移现存的使用如 http 基本或摘要身份验证的直接身份验证方案的客户端至 oauth

oauth-password-flow.png

  • 资源所有者提供给客户端它的用户名和密码
  • 通过包含从资源所有者处接收到的凭据,客户端从授权服务器的令牌端点请求访问令 牌。当发起请求时,客户端与授权服务器进行身份验证
  • 授权服务器对客户端进行身份验证,验证资源所有者的凭证,如果有效,颁发 Access Token

3.3.1 Access Token 请求

请求参数的客户端使用 application/x-www-form-urlencoded 格式向授权端点 URI 的查询部分添加下列参数构造请求 URI:

  • grant_type 必需的。值必须设置为 "password"
  • username 必需的。资源所有者的用户名。
  • password 必需的。资源所有者的密码。
  • scope 可选的。访问请求的范围。如果客户端类型是机密的或客户端被颁发了客户 端凭据(或选定的其他身份验证要求),客户端必须与 授权服务器进行身份验证。

下面是一个示例

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w

授权服务器必须:

要求机密客户端或任何被颁发了客户端凭据(或有其他身份验证要求)的客户端进行客 户端身份验证若包括了客户端身份验证,验证客户端身份,并使用它现有的密码验证算 法验证资源所有者的密码凭据。

3.3.2 Access Token 响应

如果访问令牌请求是有效的且被授权,授权服务器发访问令牌以及可选的刷新令牌。如 果请求客户端身份验证失败或无效,授权服务器返回错误响应。 一个样例成功响应:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter":"example_value"
}

3.4 (客户端)凭据许可

当客户端请求访问它所控制的,或者事先与授权服务器协商的其他资源所有者的受保护 资源,客户端可以只使用它的客户端凭据请求访问令牌

客户端凭据许可类型必须只能由机密客户端使用

oauth-client-credentials.png

  • 客户端与授权服务器进行身份验证并向令牌端点请求访问令牌
  • 授权服务器对客户端进行身份验证,如果有效,颁发访问令牌

3.4.1 Access Token 请求

请求参数的客户端使用 application/x-www-form-urlencoded 格式向授权端点 URI 的查询部分添加下列参数构造请求 URI:

  • grant_type 必需的。值必须设置为 "clientcredentials"
  • scope 可选的。访问请求的范围

下面是一个示例

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials

授权服务器必须对客户端进行身份验证。

3.4.2 Access Token 响应

如果访问令牌请求是有效的且被授权,授权服务器访问令牌以及可选的刷新令牌。刷新 令牌不应该包含在内。 如果请求因客户端身份验证失败或无效,授权服务器返回错误 响应。

一个样例成功响应:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "example_parameter":"example_value"
}

4 参考文档

Last Updated 2020-02-22 Sat 20:06. Created by Jinghui Hu at 2019-07-24 Wed 13:25.