oauth2開放認證協議原理及案例分析


之前翻譯過一篇 
OAuth認證協議原理分析及使用方法
,雖然 OAuth2還沒有正式發布,但是國內外的OAuth2的采用情況幾乎要完全替代掉OAuth1.1了。像淘寶、騰訊、人人網、百度開放平台就已經采用Oauth2,新浪微博也發來郵件說是要很快上馬OAuth2,徹底替換掉OAuth1.1。目前OAuth2到了
v20草稿階段
,最新的版本是 2011年7月25號發布的,協議變化還是很快的,所以看到國內的一些已經實現的實例,再比照官方的 oauth2,會有些出入的。

為何要 OAUTH2來替換OAUTH1.1?

  • 一、OAuth2大大簡化了認證流程,OAuth1版本,我都感覺有些流程設計不是為安全性而存在,有些東西很難想一個理由,他們為何要弄得如此復雜。復雜可能是增加安全性的一個要素,但是也極大增加了開發者的開發難度。
  • 二、增加了對多種不同方式的認證,原來的認證只能直接或間接通過瀏覽器,現在有專門的標准來給客戶端程序、移動應用、瀏覽器應用提供認證的方法。

OAUTH2的四種角色

  • resource owner資源所有者:比如twitter用戶,他在twitter的數據就是資源,他自己就是這些資源的所有者。
  • resource server資源服務器:保存資源的服務器,別人要訪問受限制的資源就要出示 Access Token(訪問另牌)。
  • client客戶端:一個經過授權后,可以代表資源所有者訪問資源服務器上受限制資源的一方。比如 開發者開發的應用。
  • authorization server授權服務器:對 資源所有者進行認證,認證通過后,向 客戶端發放 Access Token(訪問另牌)。

OAUTH2取得ACCESS TOKEN的四種方式

  • 一、Authorization Code授權碼方式:這種是推薦使用的,也是最安全的,也是替換OAuth1.1的一種授權方式。
    流程:
    1、引導用戶訪問授權服務器,比如地址:

     

     
    1
    2
    3
    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就是客戶端申請開發者的時候取得的 appkey,state是一個可選參數,可以用於保存客戶端在引導用戶轉向前的一些狀態,當回到 redirect_uri的時候會原封不動的傳回來,redirect_uri是當用戶確認授權應用訪問的時候跳轉回來的地址。
    2,用戶同意授權后跳轉回來的的地址如:

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

    &state=xyz ,其中 code就是 Authorization Code,state就是上面所說的可選參數。
    3,使用取得的 Authorization Code去換取Access Token:

     
    1
    2
    3
    4
    5
    6
    7
    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded;charset=UTF-8
     
    =authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

    其中 Authorization是由Client id(app key)及Client password(app secret)組合成的 http basic 驗證字符串,grant_type必須為 authorization_code,code是上一步取得的 Authorization Code,redirect_uri是完成后跳轉回來的網址。
    如果Client不能發送 Authorization信息,則可以使用下面的方式,/token這個地址必須是 https連接的,不然就有泄露 client secret的可能性:

     
    1
    2
    3
    4
    5
    6
    POST /token HTTP/1.1
    Host: server.example.com
    Content-Type: application/x-www-form-urlencoded;charset=UTF-8
     
    grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
    &client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

    成功的話返回的信息為:

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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"
    }
  • 二、Implicit Grant隱式授權:相比授權碼授權,隱式授權少了第一步的取Authorization Code的過程,而且不會返回 refresh_token。主要用於無服務器端的應用,比如 瀏覽器插件。隱式授權不包含Client授權,它的授權依賴於 資源所有者及注冊應用時候所填寫的redirection URI(跳轉地址)。因為Access token是附着在 redirect_uri 上面被返回的,所以這個 Access token就可能會暴露給 資源所有者或者設置內的其它方(對資源所有者來說,可以看到redirect_uri,對其它方來說,可以通過監測瀏覽器的地址變化來得到 Access token)。
    流程
    一、引導用戶訪問一個專門的授權頁面,如

     

     
    1
    2
    3
    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為appkey。可以看到這里取Access token的過程中並沒有像 第一種方式那樣傳入 client_secret。因為如果你傳入 client_secret,其實就是相當於告訴用戶,你應用的app secret了。
    二、在成功授權后,跳轉回到 redirect_uri所定義的網址

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

    ,這樣應用就可以通過取地址中的 fragment部分來取得 access token。

  • 三、Resource Owner Password Credentials資源所有者密碼證書授權:這種驗證主要用於資源所有者對Client有極高的信任度的情況,比如操作系統或高權限程序。只有在不能使用其它授權方式的情況下才使用這種方式。
    流程:
    一、提交信息到取 token頁面

     

     
    1
    2
    3
    4
    5
    6
    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded;charset=UTF-8
     
    grant_type=password&username=johndoe&password=A3ddj3w

    這里的 Authorization是 client_id為username,client_secret為password的http basic驗證碼。grant_type必須為 password,username為用戶名,password為用戶密碼。
    取得的結果如下:

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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"
    }

    Q:為何要這種這么不安全的方式?
    A:取代原來原始的 username,password的授權方式,而且不需要 client保存用戶的密碼,client只要保存access token就可以。主要用於客戶端程序。

  • 四、Client Credentials客戶端證書授權:這種情況下 Client使用自己的 client證書(如 client_id及client_secret組成的 http basic驗證碼)來獲取 access token,只能用於信任的client。
    流程:
    一、提交參數取 access token

     

     
    1
    2
    3
    4
    5
    6
    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded;charset=UTF-8
     
    grant_type=client_credentials

    其中 Authorization是client_id及client_secret組成的 http basic驗證串。grant_type必須為client_credentials,
    返回如下:

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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"
    }

國內一些OAUTH2案例分析

標准的 oauth2中,使用 access token來向資源服務器發出請求,取得資源。這里的資源服務器需要使用 https協議,否則access token極可能被其它方獲取。比如

 
1
2
3
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer 7Fjfp0ZBr1KtDRbnfVdmIw


bearer是指 token類型
,后面的字符串就是access token。還有一種 
mac類型的 token(目前v20版本的草稿里還沒有文檔)
,如:

 
1
2
3
4
5
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC id= "h480djs93hd8" ,
                    nonce= "274312:dj83hs9s" ,
                    mac= "kDZvddkndxvhGRXZhvuDjEWhGeE="

,因為 https速度相較http慢,而且並非所有服務器或客戶都支持https,所以國內一些網站采用一種http也可訪問資源的方式。


淘寶開放平台的方式
:應用通過用戶授權獲取的AccessToken的值即等同於Sessionkey,應用憑借AccessToken調用taobao API即可。查看淘寶SDK,可以看到 其使用應用的app_secret作用密碼鑰來進行簽名,參數里面包含了 這個Sessionkey,這樣淘寶在收到這個請求的時候,根據 app_id來判斷是哪個應用,根本sessionkey的值來判斷是哪個用戶,如果不傳這個 sessionkey就用 app_id查得app_id所屬的淘寶用戶就行了。也就是說 sessionkey必須配合 這個 client自己的授權資料appkey appsrecet來訪問資源。


百度開放平台方式

人人網方式
、還有騰訊也類似:在返回 access token的同時返回 sessionKey及sessionSecret。如:

 
1
2
3
4
5
6
7
8
{
     "access_token" : "1.a6b7dbd428f731035f771b8d15063f61.86400.1292922000-2346678-124328" ,
     "expires_in" : 86400,
     "refresh_token" : "2.385d55f8615fdfd9edb7c4b5ebdc3e39.604800.1293440400-2346678-124328" ,
     "scope" : "basic email" ,
     "session_key" : "9XNNXe66zOlSassjSKD5gry9BiN61IUEi8IpJmjBwvU07RXP0J3c4GnhZR3GKhMHa1A=" ,
     "session_secret" : "27e1be4fdcaa83d7f61c489994ff6ed6" ,
}

在調用資源API的時候,如下:

 
1
2
GET /rest/2.0/passport/users/getInfo?session_key=9XNNXe66zOlSassjSKD5gry9BiN61IUEi8IpJmjBwvU07RXP0J3c4GnhZR3GKhMHa1A%3D&timestamp=2011-06-21+17%3A18%3A09&format=json&uid=67411167&sign=d24dd357a95a2579c410b3a92495f009 HTTP/1.1
Host: api.example.com

這里參數里面的 session_key,傳給服務器后,用戶查詢 session_secret,sign使用session_secret作為密鑰來加密的。可以看到這里調用的時候沒有使用 client_id或client_secret信息,所以對於任何獲取

 
1
2
"session_key" : "9XNNXe66zOlSassjSKD5gry9BiN61IUEi8IpJmjBwvU07RXP0J3c4GnhZR3GKhMHa1A=" ,
"session_secret" : "27e1be4fdcaa83d7f61c489994ff6ed6" ,

的一方都可以調用到API。降低系統耦合度。

原文地址:http://kejibo.com/oauth2/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM