一文读懂Oauth2四种客户端授权模式

官网:OAuth Community Site

OAuth是一个关于授权(authorization)的开放网络工业标准,允许用户授权第三方应用访问用户存储在其它应用上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本。

An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.

翻译:

一种以简单和标准的方法在web、移动和桌面应用之间进行安全授权的开放协议

Oauth的作用

随着大量开放平台的出现,建立在开放平台之上的各种第三方应用也在大量冒出,出对安全性和统一标准的要求,于是出现了oauth协议。oauth协议旨在解决应用与第三方应用之间的授权问题。怎么理解?举个例子,在网络上有大量的应用网站,用户如果要使用不同的网站,不得不到各个应用网站进行用户注册。这对用户来讲是不够友好的,因为用户不得不记住各个网站的用户名和密码。有没有一种方法,可以让用户尽可能只使用一个账号和密码?答案当然是有,这就是我们平时常用的微信或QQ授权登录,这种登录其实就是根据Oauth协议来进行授权的。微信授权流程粗略描述如下:

  1. 用户准备登录某门户网站,用户没有账号,网站支持使用微信登录,于是用户点击微信登录

  2. 微信认证平台返回授权页面给用户

  3. 用户进行资源授权(比如允许用户昵称,头像的访问权限)

  4. 微信认证返回授权码给某门户网站

  5. 某门户网站拿授权码去微信认证平台获取token令牌

  6. 微信平台返回token令牌

  7. 某门户网站可以使用token令牌去微信平台获取此用户的头像和昵称等基础信息,获取后使用这些信息自动登录本网站

  8. 用户登录成功

这是某门户网站使用微信进行登录的简单流程,此流程即是Oauth2的授权码模式的流程,文章后续将会简介Oauth2的4种授权模式。

Oauth2角色

参看:RFC 6749 - The OAuth 2.0 Authorization Framework

  • Third-party application:第三方应用程序,或说客户端。例如上文的某门户网站。

  • Resource Owner:资源所有者,例如上文的用户。

  • Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。

  • Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

上面的角色根据具体情况具体分析,比方说我们自己开发了一个网站,我们既可以作为认证、资源服务器给其它第三方应用提供认证授权服务(比如说我们前端作为第三方应用通过密码模式去服务端进行认证授权,此时后端应用就是认证、资源服务器),也可以作为第三方应用去获取其它应用的一些信息(比如上面的微信认证登录,我们自己的网站整个可看作第三方应用,微信平台是认证、资源服务器)。

Oauth2.0协议流程

+--------+                               +---------------+
     |        |--(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 ---|               |
     +--------+                               +---------------+
​
                     Figure 1: Abstract Protocol Flow

流程解释如下:

(A)  The client requests authorization from the resource owner.  The authorization request can be made directly to the resource owner (as shown), or preferably indirectly via the authorization server as an intermediary.
​
(B)  The client receives an authorization grant, which is a credential representing the resource owner's authorization,expressed using one of four grant types defined in this specification or using an extension grant type.  The authorization grant type depends on the method used by the client to request authorization and the types supported by the authorization server.
​
(C)  The client requests an access token by authenticating with the authorization server and presenting the authorization grant.
​
(D)  The authorization server authenticates the client and validates the authorization grant, and if valid, issues an access token.
(E)  The client requests the protected resource from the resource server and authenticates by presenting the access token.
​
(F)  The resource server validates the access token, and if valid,serves the request.
​
The preferred method for the client to obtain an authorization grant from the resource owner (depicted in steps (A) and (B)) is to use the authorization server as an intermediary, which is illustrated in Figure 3 in Section 4.1.

大致如下:

  • (A)客户端请求资源所有者授权。可以直接向资源拥有者发出授权请求,但最好通过认证服务器作为中介。(授权请求经过认证服器最后才展示给用户会带来一些灵活性,比如授权服务器可以动态获取当前用户的一些最新可授权信息,然后返回一个可授权列表到前端展示给用户,用户可选择性授权,也可以部分授权)

  • (B)用户同意授权后,客户端收到一个代表资源所有者的授权的特定授权类型(取决于上一步发起授权请求指定的授权类型)的凭据。

  • (C)客户端通过上一步获取的授权凭据向认证服务器申请令牌。

  • (D)认证服务器对客户端和授权凭证进行校验,校验通过后发放令牌。

  • (E)客户端使用令牌向资源服务器请求受保护的资源。

  • (F)资源服务器校验令牌,校验通过后向客户端返回受保护的资源。

客户端的授权模式

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

  • 授权码模式(authorization code)

  • 简化模式(implicit)

  • 密码模式(resource owner password credentials)

  • 客户端模式(client credentials)

授权码模式(authorization code)

The authorization code grant type is used to obtain both access tokens and refresh tokens and is optimized for confidential clients.
Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.

认证码凭证主要用于获取access token和refresh tokens,由于此模式是一个基于重定向的流程,客户端必须能够与资源拥有者的用户代理(一般指浏览器)进行交互,并且能够接收来自认证服务器的传入请求(通过重定向)。

 +----------+
     | Resource |
     |   Owner  |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier      +---------------+
     |         -+----(A)-- & Redirection URI ---->|               |
     |  User-   |                                 | Authorization |
     |  Agent  -+----(B)-- User authenticates --->|     Server    |
     |          |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Authorization Code ---------'      |
     |  Client |          & Redirection URI                  |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)
​
   Note: The lines illustrating steps (A), (B), and (C) are broken into
   two parts as they pass through the user-agent.
​
                     Figure 3: Authorization Code Flow

流程图步骤如下:

The flow illustrated in Figure 3 includes the following steps:
​
(A)  The client initiates the flow by directing the resource owner's user-agent to the authorization endpoint.  The client includes its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted (or denied).
​
(B)  The authorization server authenticates the resource owner (via the user-agent) and establishes whether the resource owner grants or denies the client's access request.
​
(C)  Assuming the resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI provided earlier (in the request or during client registration).  The redirection URI includes an authorization code and any local state provided by the client earlier.
​
(D)  The client requests an access token from the authorization server's token endpoint by including the authorization code received in the previous step.  When making the request, the client authenticates with the authorization server.  The client includes the redirection URI used to obtain the authorization code for verification.
​
(E)  The authorization server authenticates the client, validates the authorization code, and ensures that the redirection URI received matches the URI used to redirect the client in step (C).  If valid, the authorization server responds back with an access token and, optionally, a refresh token.

大致如下:

  • (A)客户端(如某网站应用)通过用户代理(浏览器)将资源拥有者导向认证服务器(不好理解的话,回想微信登录第一步)。客户端携带、授权类型、客户端标识、请求范围、重定向url等参数请求认证服务器获取授权码。

  • (B)认证服务器对资源拥有者进行认证(如,需要用户登录微信),资源拥有者决定是否给客户端授权。

  • (C)假设用户同意授权,认证服务器将通过redirection URI重定向到用户代理(浏览器),重定向的url将会包含认证服务器返回的授权码。

  • (D)客户端通过授权码和重定向url向认证服务器申请令牌,认证服务器将会对客户端进行认证(即此客户端必须是认证服务器登记过的,例如我们开发微信登录时微信平台给我们的appId即可认为是客户端的标识)

  • (E)认证服务器对客户端、授权码、重定向url等信息进行校验,校验通过后返回access token和refresh token。

Authorization Request

A步骤客户端向认证服务器获取授权码示例:

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

请求参数如下:

  • response_type,响应类型, 必选项,授权码模式下固定值code

  • client_id,客户端标识,必选项

  • redirect_uri,重定向uri,可选项

  • scope,授权范围,可选项

  • state,当前客户端状态,可使用任意值。推荐使用。此参数可应用于预防跨站点请求伪造行为。

Authorization Response

如果资源拥有者同意授权(步骤C),认证服务器就会通过重定向uri将认证码code和客户端状态值state返回。认证服务器响应的uri会包含如下参数

  • code,授权码。授权码有效时间推荐10分钟内,而且不能重复使用,当重复使用时,认证服务器必须拒绝。

  • state,客户端状态值,当请求认证码时携带,认证服务器必须原样返回。

认证请求正常响应示例:

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

认证请求错误响应示例:

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

响应参数如下:

  • error,错误码,必选项。具体可取值如下:

    • invalid_request,请求不合法,比如缺失必须参数,携带不合法参数等。

    • unauthorized_client,客户端无权访问此方法

    • access_denied,资源拥有者或认证服务器拒绝请求

    • unsupported_response_type,认证服务器不允许认证码授权

    • invalid_scope,非法的授权范围

    • server_error,认证服务器内部错误

    • temporarily_unavailable,认证服务暂时不可用

  • state,必选项,客户端状态值,当请求认证码时携带,认证服务器必须原样返回。

  • error_description,错误描述,可选

  • error_uri,错误页地址,可选

Access Token Request

步骤D,当客户端取得了authorization code,此时可以向认证服务器申请获取令牌。请求示例:

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

参数如下:

  • grant_type,授权类型,必选项,此处为固定值authorization_code

  • code,授权码,在步骤C中获取的,必选项

  • redirect_uri,重定向uri,必选项,跟步骤A中的uri保持一致

  • client_id,客户端标识,必选项

Access Token Response

步骤E,认证服务器对客户端、授权码、重定向url等信息进行校验,校验通过后返回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":"xxx",
"token_type":"example",
"expires_in":3600,
"refresh_token":"xxx",
"example_parameter":"example_value"
}

简化模式(implicit)

The implicit grant type is used to obtain access tokens (it does not support the issuance of refresh tokens) and is optimized for public clients known to operate a particular redirection URI.  These clients are typically implemented in a browser using a scripting language such as JavaScript.
​
Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.
​
Unlike the authorization code grant type, in which the client makes separate requests for authorization and for an access token, the client receives the access token as the result of the authorization request.
​
The implicit grant type does not include client authentication, and relies on the presence of the resource owner and the registration of the redirection URI.  Because the access token is encoded into the redirection URI, it may be exposed to the resource owner and other applications residing on the same device.

简化模式下,客户端(第三方应用)不直接与认证服务器进行交互,用户代理(浏览器)直接与认证服务器进行交互获取令牌,认证服务器不需要对客户端进行认证。和授权码模式相比,简化模式省略了通过授权码去获取令牌这一步,只要资源拥有者同意授权,直接通过重定向uri返回令牌。下面是implicit模式的流程图:

+----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier     +---------------+
     |         -+----(A)-- & Redirection URI --->|               |
     |  User-   |                                | Authorization |
     |  Agent  -|----(B)-- User authenticates -->|     Server    |
     |          |                                |               |
     |          |<---(C)--- Redirection URI ----<|               |
     |          |          with Access Token     +---------------+
     |          |            in Fragment
     |          |                                +---------------+
     |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
     |          |          without Fragment      |     Client    |
     |          |                                |    Resource   |
     |     (F)  |<---(E)------- Script ---------<|               |
     |          |                                +---------------+
     +-|--------+
       |    |
      (A)  (G) Access Token
       |    |
       ^    v
     +---------+
     |         |
     |  Client |
     |         |
     +---------+
​
   Note: The lines illustrating steps (A) and (B) are broken into two
   parts as they pass through the user-agent.
​
                       Figure 4: Implicit Grant Flow

流程图步骤如下:

(A)  The client initiates the flow by directing the resource owner's user-agent to the authorization endpoint.  The client includes its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted (or denied).
​
(B)  The authorization server authenticates the resource owner (via the user-agent) and establishes whether the resource owner grants or denies the client's access request.
​
(C)  Assuming the resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI provided earlier.  The redirection URI includes the access token in the URI fragment.
​
(D)  The user-agent follows the redirection instructions by making a request to the web-hosted client resource (which does not include the fragment per [RFC2616]).  The user-agent retains the fragment information locally.
​
(E)  The web-hosted client resource returns a web page (typically an HTML document with an embedded script) capable of accessing the full redirection URI including the fragment retained by the user-agent, and extracting the access token (and other parameters) contained in the fragment.
​
(F)  The user-agent executes the script provided by the web-hosted client resource locally, which extracts the access token.
​
(G)  The user-agent passes the access token to the client.

大致如下:

  • A,客户端通过用户代理将资源拥有者导向认证服务器,携带客户端标识、重定向uri等参数

  • B,认证服务器对资源拥有者进行认证,资源拥有者决定是否给客户端授权

  • C,假设资源拥有者同意授权,认证服务器通过A步骤提供的重定向uri进行重定向,并在uri片断中附带访问令牌

  • D,用户代理向资源服务器发出请求,不包含上一步获取到的片断信息

  • E,资源服务器返回一个支持嵌入式脚本的网页,脚本能够访问上一步用户代理(浏览器)保留在本地的代码片断并从中提取出访问令牌

  • F,用户代理执行脚本,把令牌提取出来

  • G,用户代理将令牌发给客户端

Authorization Request

A步骤客户端通过用户代理向认证服务器请求令牌示例:

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

参数如下:

  • response_type:表示授权类型,此处的值固定为"token",必选项。

  • client_id:表示客户端的ID,必选项。

  • redirect_uri:表示重定向的URI,可选项。

  • scope:表示权限范围,可选项。

  • state:表示客户端的当前状态,推荐带上,可以指定任意值,认证服务器会原封不动地返回这个值。

Access Token Response

如果用户同意授权,认证服务器将会返回如下示例内容:

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

响应参数如下:

  • access_token:表示访问令牌,必选项。

  • token_type:表示令牌类型,该值大小写不敏感,必选项。

  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须通过其他方式设置过期时间。

  • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

  • state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

错误响应示例:

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

错误响应参数如下:

响应参数如下:

  • error,错误码,必选项。具体可取值如下:

    • invalid_request,请求不合法,比如缺失必须参数,携带不合法参数等。

    • unauthorized_client,客户端无权访问此方法

    • access_denied,资源拥有者或认证服务器拒绝请求

    • unsupported_response_type,认证服务器不允许认证码授权

    • invalid_scope,非法的授权范围

    • server_error,认证服务器内部错误

    • temporarily_unavailable,认证服务暂时不可用

  • state,必选项,客户端状态值,当请求认证码时携带,认证服务器必须原样返回。

  • error_description,错误描述,可选

  • error_uri,错误页地址,可选

密码模式(resource owner password credentials)

The resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the client, such as the device operating system or a highly privileged application.  The authorization server should take special care when enabling this grant type and only allow it when other flows are not viable.
​
This grant type is suitable for clients capable of obtaining the resource owner's credentials (username and password, typically using an interactive form).  It is also used to migrate existing clients using direct authentication schemes such as HTTP Basic or Digest authentication to OAuth by converting the stored credentials to an access token.

密码模式适用于资源拥有者与资源服务器之间是高度互相信任的场景。举个例子,在前后端分离架构中,后端采用Sping Security Oauth2对用户进行认证授权,对于内部用户来讲,登录后台管理系统对系统的资源进行管理,此时就适用于密码模式。我们可以把前端应用或app应用看作一个第三方应用(即客户端),把某个提供http接口的微服务看作一个资源服务器,另外有一个用于认证的oauth2认证服务器。这时前端应用(客户端)与提供服务的资源服务器、系统管理人员(资源拥有者)它们之间是高度互相信任的,此时使用密码模式最为适合。试想,假设使用授权码模式,用户登录认证后,还需要确认授权,授权完毕还需要使用授权码到认证服务器获取token,岂不是多此一举?

 +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          v
          |    Resource Owner
         (A) Password Credentials
          |
          v
     +---------+                                  +---------------+
     |         |>--(B)---- Resource Owner ------->|               |
     |         |         Password Credentials     | Authorization |
     | Client  |                                  |     Server    |
     |         |<--(C)---- Access Token ---------<|               |
     |         |    (w/ Optional Refresh Token)   |               |
     +---------+                                  +---------------+
​
            Figure 5: Resource Owner Password Credentials Flow

密码模式主要有如下几个步骤:

(A)  The resource owner provides the client with its username and password.
​
(B)  The client requests an access token from the authorization server's token endpoint by including the credentials received from the resource owner.  When making the request, the client authenticates with the authorization server.
​
(C)  The authorization server authenticates the client and validates the resource owner credentials, and if valid, issues an access token.

大致如下:

  • A,资源拥有者将用户名和密码提供给客户端

  • B,客户端通过用户名和密码向认证服务器请求令牌,认证服务器将对客户端进行校验。

  • C,认证服务器校验通过后向客户端发放令牌。

Access Token Request

B步骤中,客户端向认证服务器请求令牌示例:

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

参数如下:

  • grant_type:表示授权类型,此处的值固定为"password",必选项。

  • username:表示用户名,必选项。

  • password:表示用户的密码,必选项。

  • scope:表示权限范围,可选项。

Access Token Response

认证服务器通过后将会返回如下示例内容:

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

客户端模式(client credentials)

The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to the protected resources under its control, or those of another resource owner that have been previously arranged with the authorization server (the method of which is beyond the scope of this specification).
​
The client credentials grant type MUST only be used by confidential clients.

客户端以自己的名义向认证服务器申请令牌。通常这种模式只提供给保密用户使用,并且其授权范围是事先由认证服务器确定好的。

 +---------+                                  +---------------+
     |         |                                  |               |
     |         |>--(A)- Client Authentication --->| Authorization |
     | Client  |                                  |     Server    |
     |         |<--(B)---- Access Token ---------<|               |
     |         |                                  |               |
     +---------+                                  +---------------+
​
                     Figure 6: Client Credentials Flow

流程如下:

(A)  The client authenticates with the authorization server and requests an access token from the token endpoint.
​
(B)  The authorization server authenticates the client, and if valid,issues an access token.

大致如下:

  • A,客户端直接通过认证服务获取令牌,认证服务需要对客户端进行合法性校验

  • B,认证服务校验客户端通过,返回令牌

请求示例:

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

参数:

  • grant_type,授权范围,此处的值固定为"clientcredentials",必选项。

  • scope:表示权限范围,可选项

响应示例:

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

响应参数含义参考简化模式响应一节,不再赘述。

令牌更新

如果认证服务给客户端返回了refresh token,那么客户端就可以通过此refresh token去获取新的token以在令牌过期前对令牌进行续签,refresh token的过期时间一般会比access_token的过期时间长。请求刷新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

参数如下:

  • grant_type,必选项,此处为固定值“refresh_token”

  • refresh_token,必选项。此前认证服务给客户端返回的一个值。

  • scope,授权范围,可选项。和此前申请令牌时保持一致

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值