之前翻譯過一篇
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、引導用戶訪問授權服務器,比如地址:123GET /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,用戶同意授權后跳轉回來的的地址如:123HTTP/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:1234567POST /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的可能性:123456POST /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
成功的話返回的信息為:
123456789101112HTTP/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)。
流程
一、引導用戶訪問一個專門的授權頁面,如123GET /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所定義的網址123HTTP/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頁面123456POST /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為用戶密碼。
取得的結果如下:123456789101112HTTP/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 token123456POST /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,
返回如下:1234567891011HTTP/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×tamp=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/