oauth2.0的受權流程詳解

受權模式

1)oauth2.0 提供了四種受權模式,開發者能夠根據本身的業務狀況自由選擇。java

  • 受權碼受權模式(Authorization Code Grant)
  • 隱式受權模式(簡化模式)(Implicit Grant)
  • 密碼受權模式(Resource Owner Password Credentials Grant)
  • 客戶端憑證受權模式(Client Credentials Grant)

image.png

整個開發流程簡述一下:web

一、 在客戶端web項目中構造一個oauth的客戶端請求對象(OAuthClientRequest),在此對象中攜帶客戶端信息(clientId、accessTokenUrl、response_type、redirectUrl),將此信息放入http請求中,重定向到服務端。此步驟對應上圖1json

二、 在服務端web項目中接受第一步傳過來的request,從中獲取客戶端信息,能夠自行驗證信息的可靠性。同時構造一個oauth的code受權許可對象(OAuthAuthorizationResponseBuilder),並在其中設置受權碼code,將此對象傳回客戶端。此步驟對應上圖2瀏覽器

三、 在在客戶端web項目中接受第二步的請求request,從中得到code。同時構造一個oauth的客戶端請求對象(OAuthClientRequest),這次在此對象中不只要攜帶客戶端信息(clientId、accessTokenUrl、clientSecret、GrantType、redirectUrl),還要攜帶接受到的code。再構造一個客戶端請求工具對象(oAuthClient),這個工具封裝了httpclient,用此對象將這些信息以post(必定要設置成post)的方式請求到服務端,目的是爲了讓服務端返回資源訪問令牌。此步驟對應上圖3。(另外oAuthClient請求服務端之後,會自行接受服務端的響應信息。緩存

四、 在服務端web項目中接受第三步傳過來的request,從中獲取客戶端信息和code,並自行驗證。再按照本身項目的要求生成訪問令牌(accesstoken),同時構造一個oauth響應對象(OAuthASResponse),攜帶生成的訪問指令(accesstoken),返回給第三步中客戶端的oAuthClient。oAuthClient接受響應以後獲取accesstoken,此步驟對應上圖4bash

五、 此時客戶端web項目中已經有了從服務端返回過來的accesstoken,那麼在客戶端構造一個服務端資源請求對象(OAuthBearerClientRequest),在此對象中設置服務端資源請求URI,並攜帶上accesstoken。再構造一個客戶端請求工具對象(oAuthClient),用此對象去服務端靠accesstoken換取資源。此步驟對應上圖5服務器

六、 在服務端web項目中接受第五步傳過來的request,從中獲取accesstoken並自行驗證。以後就能夠將客戶端請求的資源返回給客戶端了。app

1.重點:受權碼模式

受權碼模式(authorization code)是功能最完整、流程最嚴密的受權模式。它的特色就是經過客戶端的後臺服務器,與"服務提供商"的認證服務器進行互動。框架

image.png

image.png

它的步驟以下:工具

(A)用戶訪問客戶端,後者將前者導向認證服務器。

(B)用戶選擇是否給予客戶端受權。

(C)假設用戶給予受權,認證服務器將用戶導向客戶端事先指定的"重定向URI"(redirection URI),同時附上一個受權碼。

(D)客戶端收到受權碼,附上早先的"重定向URI",向認證服務器申請令牌。這一步是在客戶端的後臺的服務器上完成的,對用戶不可見。

(E)認證服務器覈對了受權碼和重定向URI,確認無誤後,向客戶端發送訪問令牌(access token)和更新令牌(refresh token)。

下面是上面這些步驟所須要的參數。

A步驟中,客戶端申請認證的URI,包含如下參數:

  • response_type:表示受權類型,必選項,此處的值固定爲"code"
  • client_id:表示客戶端的ID,必選項
  • redirect_uri:表示重定向URI,可選項
  • scope:表示申請的權限範圍,可選項
  • state:表示客戶端的當前狀態,能夠指定任意值,認證服務器會原封不動地返回這個值。

下面是一個例子:

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
複製代碼

C步驟中,服務器迴應客戶端的URI,包含如下參數:

  • code:表示受權碼,必選項。該碼的有效期應該很短,一般設爲10分鐘,客戶端只能使用該碼一次,不然會被受權服務器拒絕。該碼與客戶端ID和重定向URI,是一一對應關係。
  • state:若是客戶端的請求中包含這個參數,認證服務器的迴應也必須如出一轍包含這個參數。

下面是一個例子:

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

複製代碼

D步驟中,客戶端向認證服務器申請令牌的HTTP請求,包含如下參數:

  • grant_type:表示使用的受權模式,必選項,此處的值固定爲"authorization_code"。
  • code:表示上一步得到的受權碼,必選項。
  • redirect_uri:表示重定向URI,必選項,且必須與A步驟中的該參數值保持一致。
  • client_id:表示客戶端ID,必選項。

下面是一個例子

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
複製代碼

E步驟中,認證服務器發送的HTTP回覆,包含如下參數:

  • access_token:表示訪問令牌,必選項。
  • token_type:表示令牌類型,該值大小寫不敏感,必選項,能夠是bearer類型或mac類型。
  • expires_in:表示過時時間,單位爲秒。若是省略該參數,必須其餘方式設置過時時間。
  • refresh_token:表示更新令牌,用來獲取下一次的訪問令牌,可選項。
  • 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,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }
複製代碼

從上面代碼能夠看到,相關參數使用JSON格式發送(Content-Type: application/json)。此外,HTTP頭信息中明確指定不得緩存。

2.簡化模式

簡化模式(implicit grant type)不經過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了"受權碼"這個步驟,所以得名。全部步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不須要認證。

image.png

它的步驟以下:

(A)客戶端將用戶導向認證服務器。

(B)用戶決定是否給於客戶端受權。

(C)假設用戶給予受權,認證服務器將用戶導向客戶端指定的"重定向URI",並在URI的Hash部分包含了訪問令牌。

(D)瀏覽器向資源服務器發出請求,其中不包括上一步收到的Hash值。

(E)資源服務器返回一個網頁,其中包含的代碼能夠獲取Hash值中的令牌。

(F)瀏覽器執行上一步得到的腳本,提取出令牌。

(G)瀏覽器將令牌發給客戶端。

下面是上面這些步驟所須要的參數。

A步驟中,客戶端發出的HTTP請求,包含如下參數:

  • response_type:表示受權類型,此處的值固定爲"token",必選項。
  • client_id:表示客戶端的ID,必選項。
  • redirect_uri:表示重定向的URI,可選項。
  • scope:表示權限範圍,可選項。
  • state:表示客戶端的當前狀態,能夠指定任意值,認證服務器會原封不動地返回這個值。

下面是一個例子。

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
複製代碼

C步驟中,認證服務器迴應客戶端的URI,包含如下參數:

  • access_token:表示訪問令牌,必選項。
  • token_type:表示令牌類型,該值大小寫不敏感,必選項。
  • expires_in:表示過時時間,單位爲秒。若是省略該參數,必須其餘方式設置過時時間。
  • scope:表示權限範圍,若是與客戶端申請的範圍一致,此項可省略。
  • state:若是客戶端的請求中包含這個參數,認證服務器的迴應也必須如出一轍包含這個參數。

下面是一個例子。

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

在上面的例子中,認證服務器用HTTP頭信息的Location欄,指定瀏覽器重定向的網址。注意,在這個網址的Hash部分包含了令牌。

根據上面的D步驟,下一步瀏覽器會訪問Location指定的網址,可是Hash部分不會發送。接下來的E步驟,服務提供商的資源服務器發送過來的代碼,會提取出Hash中的令牌。

3.密碼受權模式

密碼模式(Resource Owner Password Credentials Grant)中,用戶向客戶端提供本身的用戶名和密碼。客戶端使用這些信息,向"服務商提供商"索要受權。

在這種模式中,用戶必須把本身的密碼給客戶端,可是客戶端不得儲存密碼。這一般用在用戶對客戶端高度信任的狀況下,好比客戶端是操做系統的一部分,或者由一個著名公司出品。而認證服務器只有在其餘受權模式沒法執行的狀況下,才能考慮使用這種模式。

image.png

它的步驟以下:

(A)用戶向客戶端提供用戶名和密碼。

(B)客戶端將用戶名和密碼發給認證服務器,向後者請求令牌。

(C)認證服務器確認無誤後,向客戶端提供訪問令牌。

B步驟中,客戶端發出的HTTP請求,包含如下參數:

  • 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
複製代碼

C步驟中,認證服務器向客戶端發送訪問令牌,下面是一個例子。

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.客戶端模式

客戶端模式(Client Credentials Grant)指客戶端以本身的名義,而不是以用戶的名義,向"服務提供商"進行認證。嚴格地說,客戶端模式並不屬於OAuth框架所要解決的問題。在這種模式中,用戶直接向客戶端註冊,客戶端以本身的名義要求"服務提供商"提供服務,其實不存在受權問題。

image.png

它的步驟以下:

(A)客戶端向認證服務器進行身份認證,並要求一個訪問令牌。

(B)認證服務器確認無誤後,向客戶端提供訪問令牌。

A步驟中,客戶端發出的HTTP請求,包含如下參數:

  • granttype:表示受權類型,此處的值固定爲"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
複製代碼

認證服務器必須以某種方式,驗證客戶端身份。

B步驟中,認證服務器向客戶端發送訪問令牌,下面是一個例子。

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"
     }
複製代碼

更新令牌

若是用戶訪問的時候,客戶端的"訪問令牌"已通過期,則須要使用"更新令牌"申請一個新的訪問令牌。

客戶端發出更新令牌的HTTP請求,包含如下參數:

  • granttype:表示使用的受權模式,此處的值固定爲"refreshtoken",必選項。
  • refresh_token:表示早前收到的更新令牌,必選項。
  • scope:表示申請的受權範圍,不能夠超出上一次申請的範圍,若是省略該參數,則表示與上一次一致。

下面是一個例子。

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
複製代碼
相關文章
相關標籤/搜索