OAuth2.0学习一

  RFC-6749(Request For Comments(RFC),是一系列以编号排定的文件。意即“请求评论”,包含了关于Internet的几乎所有重要的文字资料。)

OAuth 2.0授权框架

  摘要:OAuth 2.0授权框架允许第三方应用程序通过如下任意一种方式获取有限制的访问:

    1、第三方应用代表资源拥有者发起在资源拥有者和HTTP服务之间的互动。

    2、第三方应用通过其身份来获取访问权限。

1、介绍

  在传统的C/S身份验证模型中,客户端通过使用资源所有者的凭据向服务器进行身份验证来请求服务器上的访问受限资源(受保护资源)。 为了向第三方应用程序能够访问受限资源,资源所有者需要与第三方共享其凭据。 这会产生一些问题和局限:

  • 为了将来的需要,第三方程序需要存储资源拥有者的凭据(通常为明文密码)
  • 即使密码验证存在安全漏洞,服务器仍然需要支持它
  • 第三方程序对资源拥有者的受保护资源拥有过于宽泛的权限,同时资源拥有者也没有能力对第三方程序进行限制(如限制第三方程序仅访问部分资源,或限制第三方程序的访问时间等)
  • 资源拥有者必须通过更改密码来撤销第三方应用的权限。并且不能对单个第三方应用撤权(一旦更改密码,所有之前授予权限的第三方应用程序都要重新授权)
  • 任意第三方应用的泄密都会导致终端用户的密码和受该密码保护的所有数据泄密。

  OAuth通过引入授权层并将客户端的角色与资源所有者的角色分开来解决这些问题。在OAuth中,客户端请求访问由资源所有者拥有并由资源服务器托管的资源,并向其颁发与资源所有者不同的凭据集。

  客户端通过获取访问令牌而不是使用资源拥有者的凭据来访问受限资源。访问令牌是一个表示特定范围,生命周期和其他访问属性的字符串。授权服务器在资源所有者的批准下才会向第三方客户端颁发访问令牌。客户端使用访问令牌来访问资源服务器托管的受保护资源。

  例如,一个终端用户(资源拥有者)可以授权打印服务(客户端)访问存储在照片共享服务(资源服务器)中的受保护照片,而无需与打印服务共享其用户名和密码。相反,她直接使用照片共享服务信任的服务器(授权服务器)进行身份验证,该服务器向打印服务发放特定凭证(访问令牌)。

  此规范旨在与HTTP([RFC2616])一起使用。在HTTP之外的任何协议上使用OAuth都超出了本规范的范围。

  作为信息文档发布的OAuth 1.0协议([RFC5849])是一个小型临时社区工作的结果。此标准跟踪规范建立在OAuth 1.0部署经验的基础上,以及从更广泛的IETF社区收集的其他用例和可扩展性要求。OAuth 2.0 协议与OAuth 1.0不向后兼容。这两个版本可以在网络上共存,并且实现可以选择支持两者。但是,本规范的目的是所有的新系统均采用OAuth2.0,OAuth1.0仅用于支持已经部署的系统。OAuth 2.0协议与OAuth 1.0协议共享的实现细节很少,所以熟悉OAuth 1.0的实施者不应该对本规范的结构和细节进行臆测。

1.1、OAuth四个角色

  • 资源所有者(resource owner): 能够对受保护资源授予访问权限的实体。当资源所有者是一个人时,它被称为终端用户。

  • 资源服务器(resource server): 托管受保护资源的服务器,能够接受和响应通过令牌对受保护的资源的请求。

  • 客户端(client): 代表资源所有者及其授权进行受保护资源请求的应用程序。术语“客户端”并不暗示任何特定的实现特征(例如,应用程序是在服务器,台式机还是其他设备上执行)。

  • 授权服务器(authorization server): 成功后,服务器向客户端发出访问令牌验证资源所有者并获得授权。

  授权服务器和资源服务器之间的交互超出了本规范的范围。授权服务器可以是与资源服务器相同的服务器或单独的实体。单个授权服务器可以发出可以被多个资源服务器接受的访问令牌。

 1.2 Protocol Flow

  Protocol Flow 抽象OAuth 2.0流程描述

  

  权限授予( Authorization Grant)是资源拥有者同意授权请求(访问受保护资源)的凭据,客户端可以用它来获取access token。 本规范定义了四种授权(grant)类型 - 授权码模式(authorization code),简化模式(implicit),密码模式(resource owner password credentials)和客户端模式(client credentials) ,以及用于定义其他类型的可扩展性机制。

1.3. Authorization Grant

  权限授予( Authorization Grant)是资源拥有者同意授权请求(访问受保护资源)的凭据,客户端可以用它来获取access token。

  四种授权(grant)类型

    授权码模式(authorization code)

    简化模式(implicit)

    密码模式(resource owner password credentials)

    客户端模式(client credentials)

  以及用于定义其他类型的可扩展性机制。

1.3.1 授权码模式(Authorization Code)

  授权码是通过授权服务器来获得的,授权服务器是客户端和资源拥有者之间的媒介。与客户端直接向资源拥有者申请权限不同,客户端通过将资源拥有者引向授权服务器(通过[RFC2616]中定义的user-agent),然后授权服务器反过来将资源拥有者redirect到client(附带上authorization code)。

  在将资源拥有者redirect到client(附带authorization code)之前,授权服务器验证资源拥有者并获取授权。因为资源拥有者仅与授权服务器进行身份验证,所以资源拥有者的凭据(用户名、密码等)永远不会泄露给客户端(尤其是第三方客户端)。

  授权码有一些重要的安全优势,比如验证client的能力,比如直接将access token传送给client而不是通过资源拥有者的user-agent(可能会将token泄露给第三方)。

1.3.2 简化模式(implicit)

  简化模式是为在浏览器中使用诸如JavaScript之类的脚本语言而优化的一种简化的授权码流程。在简化模式中,直接将access token而不是authorization code颁发给client(通过资源拥有者的授权)。grant类型为implicit,所以没有中间环节(比如用来在稍后获取access tokenauthorization code

  在简化模式中颁发access token时,授权服务器没有对client进行验证。在某些情况下,可以通过用来获取access token的重定向URI来验证client。access token可以通过访问资源拥有者的user-agent暴露给资源拥有者或者其他的应用。

  由于简化模式减少了获取access token的往返次数,所以可以提高某些客户端的响应能力和效率(比如一个运行在浏览器中的应用)。但是,应该权衡使用简化模式所带来的便捷性与其带来的安全隐患之间的利害关系(在10.3和10.16中有描述),尤其是授权码模式可用时。

1.3.3 密码模式(resource owner password credentials)

  资源拥有者密码凭据(如用户名和密码)可以用来直接用来当做一种获取access token的权限授予方式。凭据仅应当在资源拥有者高度信任client时使用(比如,应用是设备操作系统的一部分,或有较高权限的应用),并且其他授权模式(比如授权码模式)不可用时。

  尽管这种授权类型需要client直接接触资源拥有者的凭据,资源拥有者的凭据仅被用于单次的获取access token的请求。通过使用用户凭据来交换具有较长寿命的access token或者refresh token,这种授权模式可消除client在将来需要授权时对资源拥有者凭据的需求(就是说,这次通过用户凭据获取了access token,以后就可以直接通过access token而不是用户凭据来访问受限资源了)。

1.3.4 客户端模式(client credentials)

  当授权范围限于客户端控制下的受保护资源或先前与授权服务器一起安排的受保护资源时,client凭据(或其他形式的客户端身份验证)可用作权限授予。客户端凭证通常是在客户端代表自己(客户端也是资源所有者)或基于先前与授权服务器一起安排的授权请求访问受保护资源时用作权限授予。

1.4 Access Token

  access token是用来访问受限资源的凭据。access token是一个代表授予client的权限的字符串。该字符串通常对client不透明。token表示特定范围和持续时间的访问权限,由资源所有者授予,由资源服务器和授权服务器执行。

  令牌可以表示用于检索授权信息的标识符,或者可以以可验证的方式自包含授权信息(即,由一些数据和签名组成的令牌串)。client可能需要额外的身份验证凭据(超出本规范的范围)来使用令牌。

  访问令牌提供一个使用单个的资源服务器可以理解的令牌来替换其他不同的身份验证方式(如用户名+密码方式)的抽象层。这种抽象使得颁发访问令牌比用于获取它们的权限授予更具限制性,并且消除了资源服务器理解各种不同身份验证方法的需要。

  访问令牌可以具有基于资源服务器安全性要求的不同格式,结构和使用方法(例如,加密属性)。访问令牌属性和用于访问受保护资源的方法超出了本规范的范围,并由协同规范(如[RFC6750])定义。

1.5. Refresh Token

  refresh token是用于获取access token的凭据。refresh token由授权服务器颁发给client,用于在当前访问令牌变为无效或过期时获取新的访问令牌,或者获取具有相同或更窄范围的其他访问令牌(访问令牌可能具有更短的生命周期和权限少于资源所有者授权的权限。根据授权服务器的判断,发出刷新令牌是可选的。如果授权服务器发出刷新令牌,则在发出访问令牌时包括它(即图1中的步骤(D))。

  刷新令牌是表示资源所有者授予客户端的权限的字符串。该字符串通常对客户端不透明。令牌表示用于检索 授权信息的标识符。与访问令牌不同,刷新令牌仅用于授权服务器,不会发送到资源服务器。
  

  上图流程包括以下步骤:

  (A)客户端通过向授权服务器进行认证、发起权限授予来获取access token。

  (B)授权服务器验证客户端并验证权限授予授权,如果有效,则颁发访问令牌和刷新令牌。

  (C)客户端通过呈现访问令牌向资源服务器发出受保护的资源请求。

  (D)资源服务器验证访问令牌,如果有效,则为请求提供服务。

  (E)重复步骤(C)和(D)直到访问令牌到期。如果客户端知道访问令牌已过期,则跳到步骤(G);否则,它会生成另一个受保护的资源请求

  (F)由于访问令牌无效,资源服务器返回无效的令牌错误。

  (G)客户端通过向授权服务器进行身份验证并显示刷新令牌来请求新的访问令牌。该客户端身份验证的要求是基于客户端类型和授权服务器策略。

  (H)授权服务器验证客户端并验证刷新令牌,如果有效,则发出新的访问令牌(以及可选的新刷新令牌)。

1.6. TLS Version

  由于广泛的部署和已知的安全性漏洞,当本规范使用安全传输层协议(TLS)时可能存在不同的适用版本。在本协议发表时,TLS v1.2[RFC5246]是最新版本,但是部署基础非常有限,可能无法实现。TLS v1.0 [RFC2246]是最广泛的部署版本并将提供最广泛的互操作性。
  实现还可以支持满足其安全要求的其他传输层安全机制。

1.7. HTTP Redirections

  在client话说授权服务器将user-agent导向另一个目的地时,本规范广泛地使用了HTTP重定向。虽然本规范中的示例使用HTTP 302状态代码进行重定向,但是允许其他的实现通过其他方法实现重定向,这也被认为是实现细节的一部分。

1.8. Interoperability

  OAuth 2.0提供了一个具有明确定义的具有丰富的安全属性的授权框架。但是,作为一个具有许多可选组件的丰富且高度可扩展的框架,该规范本身可能会产生各种不可互操作的实现。

  此外,对于一些组件,本规范仅有部分定义或完全未定义(例如,客户端注册,授权服务器功能,endpoint发现)。如果没有这些组件,客户端必须专门手动地针对特定授权服务器和资源服务器进行配置以进行互操作。

  该框架的设计明确期望未来的工作将定义实现完整的Web级互操作性所必需的规范性配置文件和扩展。

2. Client Registration

  在启动协议之前,client向授权服务器注册。client注册的方式使用授权服务器超出了本规范的范围,但通常涉及终端用户与HTML注册表单的交互。

  客户端注册不需要客户端和授权服务器之间的直接交互。当授权服务器支持时,注册可以依赖于其他方式来建立信任并获得所需的客户端属性(例如,重定向URI,客户端类型)。例如,可以使用自发布或第三方发布的断言来完成注册,或者通过使用 可信通道执行客户端发现的授权服务器来完成注册。

  注册客户端时,客户端开发人员应该:

    指定如第2.1节所述的客户端类型,

    提供如第3.1.2节所述的client重定向URI, 以及

    包含授权服务器所需的任何其他信息(例如,应用程序名称,网站,描述,徽标图像,所接受的法律条款)。

2.1. Client Types

  OAuth根据其与授权服务器进行安全身份验证的能力定义了两种客户端类型(即,保证其客户凭证的机密性的能力):

    机密: 客户端能够维护其凭证的机密性(例如,在具有对客户端凭证具有受限访问的安全服务器上实现的客户端),或能够使用其他方式进行安全的客户端认证。

    公开: 客户端无法维护其凭据的机密性(例如,在资源所有者使用的设备上执行的客户端,例如已安装的本机应用程序或基于Web 浏览器的应用程序),并且无法通过任何其他方式进行安全的客户端身份验证。

  客户端类型标识基于授权服务器的安全身份验证定义及其可接受的客户端凭据暴露级别。授权服务器不应该对客户端类型做出假设。

  客户端可以被实现为分布式组件集,每个组件具有不同的客户端类型和安全性上下文(例如,具有基于机密服务器的组件和基于公共浏览器的组件的分布式客户端)。如果授权服务器不提供对此类客户端的支持或不提供有关其注册的指导,则客户端应该将每个组件注册为单独的客户端。

  此规范是围绕以下客户端配置设计的:

    Web应用程序 Web应用程序是在Web 服务器上运行的机密客户端。资源所有者通过在资源所有者使用的设备上的用户代理中呈现的HTML用户界面来访问客户端。客户端凭据以及发布到客户端的任何访问令牌都存储在Web服务器上,不会向资源所有者公开或访问。

    基于用户代理的应用程序 基于用户代理的应用程序是公共客户端,其中客户端代码从web服务器下载并在资源所有者使用的设备上的用户代理(例如,web浏览器)内执行。协议数据和凭证可以轻松访问(并且通常可见)资源所有者。由于此类应用程序驻留在用户代理中,因此它们可以在请求授权时无缝使用用户代理功能。

    本机应用程序 本机应用程序是在资源所有者使用的设备上安装和执行的公共客户端。资源所有者可以访问协议数据和凭证。这是假设的可以提取应用程序中包含的任何客户端身份验证凭据。另一方面,动态发布的凭证(例如访问令牌或刷新令牌)可以获得可接受的保护级别。至少,这些凭据受到保护,从而免受应用程序可能与之交互的恶意服务器的影响。在某些平台上,可能会保护这些凭据免受驻留在同一设备上的其他应用程序的影响。

2.2. Client Identifier
  授权服务器向已注册的client颁发client identifier–一个代表该client注册信息的唯一字符串。client identifier不需要保密,它被暴露给资源拥有者并且禁止单独用于client认证。客户端标识符对于授权服务器是唯一的。
本规范未定义client identifier字符串的大小。客户端应避免对标识符大小进行假设。授权服务器应该记录它发出的任何标识符的大小。

2.3. Client Authentication

  如果客户端类型是机密的,则客户端和授权服务器建立适合授权服务器的安全性要求的客户端认证方法。授权服务器可以接受满足其安全要求的任何形式的客户端身份验证。

  机密客户端通常被颁发(或建立)用于与授权服务器进行认证的一组客户机凭证(例如,密码,公钥/私钥对)。

  授权服务器可以与公共客户端建立客户端身份验证方法。但是,授权服务器不得依赖公共客户端身份验证来识别客户端。

  客户端在每个请求中最多使用一种身份验证方法。

2.3.1. Client Password

  拥有客户端密码的客户端可以使用[RFC2617]中定义的HTTP Basic身份验证方案向授权服务器进行身份验证。使用附录B中的application/x-www-form-urlencoded编码算法对客户端标识符进行编码,并将编码value用作username;客户端密码使用相同的算法进行编码并用作password。授权服务器必须支持HTTP基本身份验证方案,以便对发出客户端密码的客户端进行身份验证。

  例如:Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

  或者,授权服务器可以选择支持在请求体中包含如下参数的客户端凭据:

  client_id : REQUIRED。在2.2节描述的注册过程中发给客户端的客户端标识符。

  client_secret : REQUIRED. The client secret. 如果客户端密钥是空字符串,则客户端可以省略该参数。

  使用这两个参数在请求体中包含客户端凭证是不推荐的,并且应该仅限于无法直接使用HTTP基本身份验证方案(或其他基于密码的HTTP身份验证方案)的客户端。参数只能在请求体中传输,绝不能包含在请求URI中。

  例如,使用body参数刷新访问令牌(第6节)的HTTP请求(额外换行符仅用于排版目的):

 POST /token HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded

     grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

  当使用密码验证发送请求时,授权服务器必须要求使用如1.6节所述的TLS。

  由于此客户端身份验证方法涉及密码,因此授权服务器必须保护使用它的任何endpoint 免受穷举攻击。

2.3.2. Other Authentication Methods

  授权服务器可以支持符合其安全要求的任何合适的HTTP认证方案。使用其他身份验证方法时,授权服务器必须定义客户端标识符(注册记录)和身份验证方案之间的映射。

2.4. Unregistered Clients

  此规范不排除使用未注册的客户端。但是,此类客户端的使用超出了本规范的范围,需要进行额外的安全性分析并检查其互操作性影响。

3. Protocol Endpoints

  授权过程使用两个授权服务器端点(HTTP资源):

  Authorization endpoint: 客户端使用该端点通过用户代理重定向从资源所有者获取授权。

  Token endpoint: 客户端用于通过user-agent redirection从资源所有者获取授权。

以及一个客户端端点:

  Redirection endpoint 授权服务器用于通过资源所有者 user-agent将包含授权凭据的响应返回给客户端。

  并非每种授权授权类型都使用两个端点。

  扩展授权类型可以根据需要定义其他端点。

3.1. Authorization Endpoint
  授权终端用于与资源所有者交互并获得权限授予。 授权服务器必须首先验证资源所有者的身份。 授权服务器验证资源所有者的方式(例如,用户名和密码登录,会话cookie)超出了本规范的范围。

  客户端获取授权端点位置的方法超出了本规范的范围,因为这个位置通常由服务文档提供。

  端点URI可以包括application/x-www-form-urlencoded格式(根据附录B)的查询组件([RFC3986]第3.4节),并且在添加其他查询参数时该组件必须保留。终端URI绝不能包含片段组件。

  由于对授权端点的请求导致用户身份验证和凭据的明文传输(在HTTP响应中),在向授权端点发送请求时,授权服务器必须使用第1.6节中所述的TLS。对于没有值的参数,必须当作在请求中省略了该参数。授权服务器必须忽略无法识别的请求参数。请求和响应参数不得被包含多次。

  授权服务器必须支持对授权端点使用HTTP“GET”方法[RFC2616],并且也可以支持使用“POST”方法。

3.1.1. Response Type

  授权终端由授权代码模式和简化授权模式的工作流中使用。客户端使用以下参数通知授权服务器所需的授权类型:

  response_type: REQUIRED. 值必须是用于请求授权代码的“code”之一,如第4.1.1节所述,“token”用于请求访问令牌(简化授权),如4.2.1节所述,或者注册的扩展值,如第8.4节。

  扩展响应类型可以包含空格(%x20)分隔的值列表,其中值的顺序无关紧要(例如,响应类型“a b”与“b a”相同)。这种复合响应类型的含义由它们各自的规范定义。

  如果授权请求缺少“response_type”参数,或者不理解响应类型,授权服务器必须返回如第4.1.2.1节所述的错误响应。

3.1.2. Redirection Endpoint

  完成与资源所有者的交互后,授权服务器将资源所有者的用户代理指向客户端。在用户注册过程中或在发出授权请求时,授权服务器将user-agent重定向到先前与授权服务器建立的客户端重定向端点。

  重定向端点URI必须是[RFC3986]第4.3节定义的绝对URI。端点URI可以包括application/x-www-form-urlencoded格式的(附录B)查询组件([RFC3986]第3.4节),并且在添加其他查询参数时必须保留该组件。端点URI绝不能包含片段组件。

3.1.2.1. Endpoint Request Confidentiality

  当请求的响应类型是“code”或“token”时,或者当重定向请求将导致在开放网络上传输敏感凭证时,重定向端点应该使用如第1.6节所述的TLS。此规范并未强制要求使用TLS,因为在撰写本文时,要求客户端部署TLS对许多客户端开发人员来说是一个重大障碍。如果TLS不可用,授权服务器应该在重定向之前警告资源所有者关于不安全端点(例如,在授权请求期间显示消息)。

  缺乏TLS会严重影响客户端及其授权访问的受保护资源的安全性。当授权过程以委托的终端用户授权的形式被用作客户端(例如,第三方登录服务)使用时,TLS的使用尤其重要。

3.1.2.2. Registration Requirements

  授权服务器必须要求以下客户端注册其重定向端点:

    公共客户。

    使用简化授权类型的机密客户端。

  授权服务器应该在使用授权端点之前要求所有客户端注册其重定向端点。

  授权服务器应该要求客户端提供完整的重定向URI(客户端可以使用“state”请求参数来实现按请求定制)如果要求注册完整的重定向URI是不可能的,授权服务器应该要求注册URI方案,权限和路径(允许客户端在请求授权时仅动态改变重定向URI的查询组件)。

  授权服务器可以允许客户端注册多个重定向端

  若无重定向注册,攻击者可能使用授权端点用作开放重定向器(如第10.15节中所述)。

  3.1.2.3. Dynamic Configuration

  如果已注册了多个重定向URI,或者只注册了部分重定向URI,或者没有注册重定向URI,则客户端必须使用“redirect_uri”请求参数包含带有授权请求的重定向URI。

  当授权请求中包含重定向URI时,如果注册了任一重定向URI,授权服务器必须将接收到的值与按照[RFC3986]第6节中定义的重定向URI列表中至少一个已注册重定向URI(或URI组件)进行匹配。如果客户端注册包含完整重定向URI,则授权服务器必须使用[RFC3986]第6.2.1节中定义的简单字符串比较法来比较两个URI。

3.1.2.4. Invalid Endpoint

  如果授权请求由于重定向URI的缺少,无效或不匹配的而未通过验证,则授权服务器应当通知资源所有者该错误,并且不得自动将用户代理重定向到无效的重定向URI。

3.1.2.5. Endpoint Content

  对客户端点的重定向请求通常会导致由user-agent处理的HTML文档响应(就是通常会返回一个网页)。如果HTML响应直接作为重定向请求的结果提供,则HTML文档中包含的任何脚本都将以完全访问重定向URI及其包含的凭据的方式执行。

  客户端不应在重定向端点响应中包含任何第三方脚本(例如,第三方分析,社交插件,广告网络)。相反,它应该从URI中提取凭据并将用户代理再次重定向到另一个端点,而不暴露凭证(在URI或其他地方)。如果包含第三方脚本,客户端必须确保首先执行自己的脚本(用于从URI中提取和删除凭据)

3.2. Token Endpoint

  客户端使用令牌端点通过呈现其权限授予或刷新令牌来获取访问令牌。除了简化授权类型之外,令牌端点与每个权限授予一起使用(因为访问令牌被直接发出)。

  客户端获取令牌端点位置的方法超出了本规范的范围,因为这通常由服务文档提供。

  端点URI可以包括application/x-www-form-urlencoded格式的(附录B)查询组件([RFC3986]第3.4节),并且在添加其他查询参数时必须保留该组件。端点URI绝不能包含片段组件。

  由于对token端点的请求导致用户身份验证和凭据的明文传输(在HTTP响应中),在向授权端点发送请求时,授权服务器必须使用第1.6节中所述的TLS。对于没有值的参数,必须当作在请求中省略了该参数。授权服务器必须忽略无法识别的请求参数。请求和响应参数不得被包含多次。

3.2.1. Client Authentication

  在向令牌端点发出请求时,Confidential clients或其他clients发出的客户端凭证必须使用授权服务器进行身份验证,如第2.3节所述。客户端身份验证用于:

  • 强制将刷新令牌和授权码绑定到发给它们的客户端。当授权代码通过不安全的通道传输到重定向端点或者重定向URI尚未完整注册时,客户端身份验证至关重要。
  • 通过禁用客户端或更改其凭据从受感染的客户端恢复,从而防止攻击者滥用被盗的刷新令牌。更改单组客户端凭据比撤消整组刷新令牌要快得多。
  • 实施身份验证管理最佳实践,这需要定期进行凭据轮换。旋转整组刷新令牌可能具有挑战性,而单组客户端凭证的轮换则更加容易。

  客户端可以在向令牌端点发送请求时使用“client_id”请求参数来对自身进行标识。在对token令牌端口的“authorization_code”“grant_type”请求中,未经身份验证的客户端必须发送其“client_id”以防止自己无意中接受用于具有不同“client_id”的客户端的代码。这可以保护客户端不会替换身份验证代码。 (它不为受保护资源提供额外的安全性。)

3.3. Access Token Scope

  授权和令牌端点允许客户端使用“范围”请求参数指定访问请求的范围。反过来,授权服务器使用“范围”响应参数来通知客户端发出的访问令牌的范围。

  scope参数的值表示为以空格分隔的区分大小写的字符串列表。字符串由授权服务器定义。如果该值包含多个以空格分隔的字符串,则它们的顺序无关紧要,并且每个字符串都会为请求的范围添加其他访问范围。

scope       = scope-token *( SP scope-token )
  scope-token = 1*( %x21 / %x23-5B / %x5D-7E )

  根据授权服务器策略或资源所有者的指示,授权服务器可以完全或部分忽略客户端请求的范围。如果发布的访问令牌范围与客户端请求的范围不同,则授权服务器必须包含“scope”响应参数,以通知客户端授予的实际范围。

  如果客户端在请求授权时省略了scope参数,则授权服务器必须使用预定义的默认值处理请求,或者使请求失败,指示范围无效。授权服务器应该记录其范围要求和默认值(如果已定义)。

4. Obtaining Authorization 获得授权

  要请求访问令牌,客户端需从资源所有者处获取授权。授权以authorization grant的形式表示,客户端使用该authorization grant来请求访问令牌。OAuth定义了四种授权类型authorization code, implicit, resource owner password credentials, 和 client credentials。它还提供了一种用于定义其他授权类型的扩展机制。

4.1. 授权码模式(Authorization Code Grant)

  authorization code grant type 通常用于获取access tokens和 refresh tokens,并且针对confidential clients进行了优化。由于这是一个基于重定向的流程,客户端必须有能力和资源拥有者的user-agent(通常为WEB浏览器)进行交互,并且有能力接收来自授权服务器的重定向请求。

  

  上图表包含如下步骤:

(A)client通过将资源拥有者重定向到授权服务器来初始化这个流程。client需要在请求中包含client identifier, requested scope, local state, and a redirection URI,这些内容在client被赋予(或者被拒绝)权限后也会被发送回来。

(B)授权服务器通过user-agent来对资源拥有者进行身份验证,并确定资源所有者是否授予或拒绝客户端的访问请求。

(C)假设资源所有者授予访问权限,授权服务器使用先前提供的重定向URI(在请求中或在客户端注册期间)将用户代理重定向回客户端。重定向URI包含授权代码和客户端先前提供的任一本地状态。

(D)客户端通过包含在上一步骤中接收的授权代码来请求来自授权服务器的令牌端点的访问令牌。发出请求时,客户端使用授权服务器进行身份验证。客户端通过包含用于获取验证授权码的重定向URI进行 验证。

(E)授权服务器对客户端进行身份验证,验证授权代码,并确保收到的重定向URI与步骤(C)中用于重定向客户端的URI相匹配。

4.1.1. 授权请求(Authorization Request)

客户端通过使用application/x-www-form-urlencoded格式将以下参数添加到授权端点URI的查询组件来构造请求URI(附录B):

  response_type : REQUIRED. Value MUST be set to “code”.

  client_id :REQUIRED. The client identifier as described in Section 2.2.

  redirect_uri : OPTIONAL. As described in Section 3.1.2.

  scope : OPTIONAL. The scope of the access request as described by Section 3.3.

  state : RECOMMENDED. 客户端用于维护请求和回调之间状态的不透明值。当授权服务器在将用户代理重定向回客户端时包含此值。这个参数应当被用来方式CSRF攻击 (参见10.12节)。

客户端使用HTTP重定向响应或通过用户代理可用的其他方式将资源所有者定向到构造的URI。

例如,client使用TLS将user-agent定向到如下HTTP请求:

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

  为确保所有必须的参数都被呈现并且合法,授权服务器需要验证请求。如果请求合法,授权服务器对资源所有者进行身份验证并获取授权决策(通过询问资源所有者或通过其他方式建立批准)。

  建立决策时,授权服务器使用HTTP重定向响应或通过用户代理可用的其他方式将用户代理指向提供的客户端重定向URI。

4.1.2. 授权响应(Authorization Response)

如果资源所有者授予访问请求,则授权服务器通过使用application/x-www-form-urlencoded格式将以下参数添加到重定向URI的查询组件来发布授权代码并将其传递给客户端(参见附录B):
  code :REQUIRED. 授权服务器生成的授权码。授权代码必须在发布后尽快过期,以减少泄漏风险。建议最长授权代码生存期为10分钟。客户端不得多次使用授权码。如果授权代码被多次使用,授权服务器必须拒绝该请求,并且应该(如果可能)撤销先前基于该授权代码发出的所有令牌。授权代码与客户端标识符和重定向URI绑定。

  state: REQUIRED if the “state” parameter was present in the client authorization request. The exact value received from the client.

例如,授权服务器通过发送如下HTTP响应来重定向user-agent:

HTTP/1.1 302 Found
     Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

   客户端必须忽略无法识别的响应参数。本规范未定义授权代码字符串大小。客户端应避免对代码值大小进行假设。授权服务器应该记录由它发出的任何码值的大小。

4.1.2.1. 异常响应(Error Response)

如果因为缺失、无效或不匹配的URI,或者客户端的identifier 缺失或无效而导致请求失败authorization server应当将这些错误通知给资源拥有者而不能自动将user-agent重定向到无效的URI。

如果资源拥有者拒绝了访问请求,或因为其他原因失败,authorization server 应当以附录B所示的格式,以application/x-www-form-urlencoded 的编码添加如下参数:

error :REQUIRED. 一个单个ASCII错误码。值域如下:
        invalid_request :The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
        unauthorized_client :The client is not authorized to request an authorization code using this method.
        access_denied :The resource owner or authorization server denied the request.
        unsupported_response_type :The authorization server does not support obtaining an authorization code using this method.
        invalid_scope :The requested scope is invalid, unknown, or malformed.
        server_error : The authorization server encountered an un condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)
        temporarily_unavailable :The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)

Values for the “error” parameter MUST NOT include characters outside the set %x20-21 / %x23-5B / %x5D-7E.

  error_description : OPTIONAL. Human-readable ASCII [USASCII] text providing additional information, used to assist the client developer in understanding the error that occurred. Values for the “error_description” parameter MUST NOT include characters outside the set %x20-21 / %x23-5B / %x5D-7E.

  error_uri :OPTIONAL. A URI identifying a human-readable web page with information about the error, used to provide the client developer with additional information about the error. Values for the “error_uri” parameter MUST conform to the URI-reference syntax and thus MUST NOT include characters outside the set %x21 / %x23-5B / %x5D-7E.

  state :REQUIRED if a “state” parameter was present in the client authorization request. The exact value received from the client.

For example, the authorization server redirects the user-agent by sending the following HTTP response:

HTTP/1.1 302 Found
   Location: https://client.example.com/cb?error=access_denied&state=xyz

 4.1.3. 授权令牌请求(Access Token Request)

client通过向token终端发送如下HTTP请求体(application/x-www-form-urlencoded格式、UTF-8编码的参数)

    grant_type :REQUIRED. Value MUST be set to “authorization_code”.

    code : REQUIRED. The authorization code received from the authorization server.

    redirect_uri :REQUIRED, if the “redirect_uri” parameter was included in the authorization request as described in Section 4.1.1, and their values MUST be identical.

    client_id :REQUIRED, if the client is not authenticating with the authorization server as described in Section 3.2.1.

If the client type is confidential or the client was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server as described in Section 3.2.1.

For example, the client makes the following HTTP request using TLS (with extra line breaks for display purposes only):

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

     grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

4.1.4. 访问令牌响应(Access Token Response)

   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"
     }

4.2. 简化模式(Implicit Grant)

 

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

(A) 客户端通过将资源所有者的用户代理定向到授权终结点来启动流。客户端包括其客户端标识符、请求的作用域、本地状态和重定向URI,授权服务器将在授予(或拒绝)访问权限后将用户代理发送回该URI。

(B) 授权服务器(通过用户代理)对资源所有者进行身份验证,并确定资源所有者是否授予或拒绝客户端的访问请求。

(C) 假设资源所有者授予访问权限,授权服务器使用前面提供的重定向URI将用户代理重定向回客户端。重定向URI在URI片段中包含访问令牌。

(D) 用户代理遵循重定向指令,向web托管的客户机资源(不包括每个[RFC2616]的片段)发出请求。用户代理在本地保留片段信息。

(E) web托管的客户机资源返回一个网页(通常是带有嵌入脚本的HTML文档),该网页能够访问完整的重定向URI,包括用户代理保留的片段,并提取片段中包含的访问令牌(和其他参数)。

(F) 用户代理在本地执行web托管客户机资源提供的脚本,该脚本提取访问令牌。

(G) 用户代理将访问令牌传递给客户端。

请参阅第1.3.2节和第9节了解使用隐式授权的背景。

使用隐式授权时的重要安全考虑见第10.3节和第10.16节。

4.2.1. Authorization Request

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

4.2.2. Access Token Response

HTTP/1.1 302 Found
     Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
               &state=xyz&token_type=example&expires_in=3600

4.2.2.1. Error Response

HTTP/1.1 302 Found
   Location: https://client.example.com/cb#error=access_denied&state=xyz

4.3. Resource Owner Password Credentials Grant

4.3.2. Access Token Request

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

4.3.3. Access Token Response

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"
     }

4.4. Client Credentials Grant

  

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

(A) 客户端使用授权服务器进行身份验证,并从令牌终结点请求访问令牌。

(B) 授权服务器对客户端进行身份验证,如果有效,则发出访问令牌。

4.4.2. Access Token Request

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

     grant_type=client_credentials

   The authorization server MUST authenticate the client.

4.4.3. Access Token Response

 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.5. Extension Grants 延期许可

POST /token HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded

     grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-
     bearer&assertion=PEFzc2Vyd[...omitted for brevity...]Q-PC9Bc3NlcnRpb24-

5. Issuing an Access Token 颁发访问令牌

5.1. Successful Response

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"
     }

5.2. Error Response

HTTP/1.1 400 Bad Request
    Content-Type: application/json;charset=UTF-8
    Cache-Control: no-store
    Pragma: no-cache

    {
      "error":"invalid_request"
    }

6. Refreshing an Access Token

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

     grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

7. Accessing Protected Resources  

7.1. Access Token Types

GET /resource/1 HTTP/1.1
     Host: example.com
     Authorization: Bearer mF_9.B5f-4.1JqM
GET /resource/1 HTTP/1.1
     Host: example.com
     Authorization: MAC id="h480djs93hd8",
                        nonce="274312:dj83hs9s",
                        mac="kDZvddkndxvhGRXZhvuDjEWhGeE="

未完待续。。。

  参考:

    OAuth

    理解OAuth 2.0

    OAuth 2.0 的一个简单解释

    OAuth 2.0 的四种方式

    RFC 6749

    RFC 6749 read the doc

    Oauth2.0 ( RFC-6749 ) 中文译文

    

原文地址:https://www.cnblogs.com/hofmann/p/12985697.html