My understanding of OAuth 1.0

引子

網上現在介紹OAuth時,大多是把OAuth core中的3 steps和一張summary圖copy過來完事。

OAuth Authentication is done in three steps:

  1. The Consume r obtains an unauthorized Request Token.
  2. The User authorizes the Request Token.
  3. The Consumer exchanges the Request Token for an Access Token.

有圖有真相:http://oauth.net/core/diagram.png

 

好吧,

如果你能拿起筆來順手就畫出3steps,理解就基本ok。

如果你可以自己寫個oauth client,整個spec的細節都已掌握。

如果你可以自己實現oauth server,則算是融匯貫通了。

如果你知道oauth的安全漏洞和微弱環節,那麼你肯定是安全專家。

 

本篇文章的目標是第一個,幫你理解oauth。

My understanding of OAuth

what's the problem it solve?

3 legs problem. 隨着web2.0的興起,大量的網站都提供了API來暴露用戶的數據給第三方應用。web2.0是啥,就是UGC(user generated content),從blog, photo到現在的sns,微博。大量的用戶產生了大量的數據,這些網站漸漸演變成一個平臺。第三方可以接入平臺,開發自己的應用。而接入,就是調用平臺提供的API得到用戶的數據,衍生自己的應用。

 

用例一:用戶使用每個網站和應用時,首先需要註冊,填入ID,登錄密碼,郵箱,姓名等等個人資料。如果是在某開放平臺上開發,則可省去這一環,用戶登錄平臺後可授權應用開發商,將自己的個人資料從平臺中導入。(openid + oauth 提供了完整的用戶免註冊問題)

 

用例二:照片打印服務(官網中的例子)。有用戶在Flick或者Picassa上傳了一次在三藩旅遊的照片,然後他想通過另外一個照片打印服務商(比較便宜)將這次旅遊的照片打印成冊。

 

Basic auth時代,用戶直接將自己的username和password告訴給第三方應用。比如名單導入和好友邀請,網站會提示:請輸入msn用戶和密碼,本網站將保證不會泄漏.....

 

直接交出用戶名和密碼無疑是很危險的事

  • No control of the access. "本網站保證不會泄漏....",不代表該網站不會在取得你的聯繫人名單時,順帶定期讀取你的email,分析email內容,給你投放定向廣告。打印服務商可能不光是將三藩旅遊的照片打印出來,可能你XXOO的也一併捎帶。

不交出用戶名和密碼,如何授權給應用?

  • oauth is try to solve the delegation (authorization) problem in a secure way in non https-environments 

Some knowledge about security 

oauth問題很簡單,然而過程卻有點trouble。要理解這些過程,首先補充下關於計算機網絡安全的知識。

數字簽名

在現實生活中,我們使用銀行卡時,需要卡號(ID)和密碼;網站登錄需要ID(user)和Password。ID是用戶唯一標認,而password則是用戶身份驗證(authentication)

 

數字簽名的作用一樣:A valid digital signature gives a recipient reason to believe that the message was created by a known sender, and that it was not altered in transit. 

一是驗證文檔用戶(authentication)的身份,二是保證其沒被更改(integration) -- 好比我們手填一些單子時,不容許有塗改。

 

怎樣做呢?把用戶的ID和password連同文檔一塊發出去? 搞計算機密碼學的不同意! 

  • unencrypted password is not allowed in computer cryptology

我們使用信用卡時,無需透露信用卡給商家,只需一個簽名即可。密碼學的同仁採取了類似的做法:

  1. 使用hash fucntion生成文檔(數據)的一個hash值。具體的hash函數不作深究,比如:取模hash,可以將所有data的byte直接相加,然後取個模。
  2. 用一個private key將hash值加密形成數字簽名。具體的加密算法不作深究,比如:將hash值和private key進行異或操作。
  3. 把用戶的Certificate (treat as a ID)和數字簽名(treat as password)連同文檔一塊發出。

服務器端

  1. 根據文檔的Certificate找到用戶對應的public key。
  2.  使用public key來解密hash value, 得到原始hash值。對應上文:將hash值和public key進行異或操作(假定是shared secret key, 公鑰和私鑰相同)
  3. 使用相同的hash function計算生成文檔的hash值。對應上文:取模hash
  4. 將兩個hash值比較。如果不同,則說明文檔或者被篡改(data is changed),或者用戶身份不對(public key is not right, so certificate is not right)

 

 

 

http://en.wikipedia.org/wiki/File:Digital_Signature_diagram.svg

hash function

 MD5 (Message-Digest algorithm 5):生成 128-bit (16-byte) hash value. 32個16進制數(4 bit一個hexadecimal number.)

 

 SHA1 (Secure Hash Algorithm): 生成160-bit hash value.

signature method(加密方法)

HMAC(Hash-based Message Authentication Code)

HMAC-SHA1

 

RSA(RivestShamir and Adleman ) is an algorithm for public-key cryptography 

RAS-SHA1

Some knowledge about sniffing the network

重放攻擊:將合法的請求重新發給服務器,從而獲取用戶數據。

 

防止重放攻擊:在request中加入nonce(number used once),一個隨機的unique string。服務器端在響應一次請求後,如果第二次接到相同的相應,可認爲這是個重放攻擊,直接reject。

 

timstamp: server端要實現重放攻擊,必須記錄所有曾經的nonce值,超超大的數據庫才行。爲了降低server端維護nonce的成本,request加入時間戳。server端只記錄一段時間內的nonce值(比如一個小時內),如果timestamp older 1小時,server端可直接reject。因爲沒有保存更老的nonce值,無法驗證其unique。

The concept(Terminology) of oauth

client:  An HTTP client, 第三方應用(曾經叫consumer)

server:  An HTTP client,擁有資源或者響應授權請求(authenticated requests)的平臺

protected resource:用戶數據

resource owner:用戶

credentials(證書):可理解爲ID和Password。如同前文介紹,oauth使用數字簽名的一套,所以不完全等同。

  • client credentials: consumer key/secret (nearly same with ID/password)
  • temporary credentials: the authorization request (request token/secret)
  • token: access grant (access token/secret)

token:上面credentials中的token,表示用戶對某個應用的授權。唯一標示符和一個相應的shared-secret來簽名加密(驗證身份)

理論上只要兩種credentials即可,一個是client應用本身的key/secret來標識應用;另外一個是表示用戶對應用的授權,用戶同意第三方應用訪問用戶的數據後,由server端生成一組access token/secret。第三方應用使用該授權(唯一標識符+secret)請求用戶的數據。oauth的目標在此體現:

The decoupling of the User’s username and password from the Token is one of the most fundamental aspects of the OAuth architecture.

token/secret 和 username/password的區別在哪?理論上我們也可以使用password來進行數字簽名,避免密碼的明文傳輸。使用token的好處是可以隨時revoke,可以有不同的access control。比如同一個用戶授權A訪問folder1,授權B訪問folder2,生成不同的token,互不影響。比如限制一個token的有效期爲1小時,平臺不可能要求用戶每一小時更換一個密碼。

 

順延這個思路,consumer key/consumer sercet作爲應用的唯一標識,欠缺一定的靈活性。引入request token/secret,增加更多的控制。比如同樣可以爲request token設置有效期,如果應用在1小時內仍沒有使用該token取得任何用戶的授權,則該request token 過期。在oauth2中request token變爲refresh token,由server端在返回access token時一塊返回,簡化了流程。

The process of oauth

From the user point (user channel)

從用戶的角度看,過程如下:

  • 訪問某個應用
  • 被重定向到平臺,提示yes or no授權給應用。
  • 點擊yes(如果沒有登錄平臺,則需輸入用戶名和密碼),被重定向迴應用頁面
  • 應用頁面顯示用戶的數據

Backgroud channel

step1, 在用戶訪問應用頁面時,client get request token from server。Authorization header的內容如下,不考慮驗證部分,consumer_keycallback爲輸入,request_token/secret爲輸出

Request  

     POST /request_temp_credentials HTTP/1.1
     Host: server.example.com
     Authorization: OAuth realm="Example",
        oauth_consumer_key="jd83jd92dhsh93js",
        oauth_signature_method="PLAINTEXT",
        oauth_callback="http%3A%2F%2Fclient.example.net%2Fcb%3Fx%3D1",
        oauth_signature="ja893SD9%26"

Response  

     HTTP/1.1 200 OK
     Content-Type: application/x-www-form-urlencoded

     oauth_token=hdk48Djdsa&oauth_token_secret=xyz4992k83j47x0b&
     oauth_callback_confirmed=true

 

 

step2, 用戶被重定向到平臺授權頁面。請求輸入爲第一步中返回的request_token, 輸出爲verifier(request_toekn原樣返回)

Request (重定向到平臺)

     GET /authorize_access?oauth_token=hdk48Djdsa HTTP/1.1
     Host: server.example.com
Response(重定向返回應用)
    GET /cb?x=1&oauth_token=hdk48Djdsa&oauth_verifier=473f82d3 HTTP/1.1
    Host: client.example.net

 

 

setp3, client使用consumer_key, request_token, verifier來換取access_token

Request

   POST /request_token HTTP/1.1
     Host: server.example.com
     Authorization: OAuth realm="Example",
        oauth_consumer_key="jd83jd92dhsh93js",
        oauth_token="hdk48Djdsa",
        oauth_signature_method="PLAINTEXT",
        oauth_verifier="473f82d3",
        oauth_signature="ja893SD9%26xyz4992k83j47x0

Response

     HTTP/1.1 200 OK
     Content-Type: application/x-www-form-urlencoded

     oauth_token=j49ddk933skd9dks&oauth_token_secret=ll399dj47dskfjd

 

接下應用使用consumer_key, access_token來取得用戶數據,這時需要加入noncetimestamp防止重放攻擊。
   POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
     Host: example.com
     Content-Type: application/x-www-form-urlencoded
     Authorization: OAuth realm="Example",
                    oauth_consumer_key="9djdj82h48djs9d2",
                    oauth_token="kkk9d7dh3k39sjv7",
                    oauth_signature_method="HMAC-SHA1",
                    oauth_timestamp="137131201",
                    oauth_nonce="7d8f3e4a",
                    oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"

     c2&a3=2+q

The sign of oauth

上面3步,其簽名過程都一致(所有的Authorization header中都加入了signature_method和signature), 數字簽名用的key是(HMAC-SHA1:consumer_secret&token_secret).

簽名的內容(base string)如下。spec中詳細定義了簽名的base string內容和編碼,

其中parameter部分包括所有The OAuth HTTP "Authorization" header field(除了oauth_signature)

1.  The HTTP request method in uppercase.  For example: "HEAD",
       "GET", "POST", etc.  If the request uses a custom HTTP method, it
       MUST be encoded (Section 3.6).

   2.  An "&" character (ASCII code 38).

   3.  The base string URI from Section 3.4.1.2, after being encoded
       (Section 3.6).

   4.  An "&" character (ASCII code 38).

   5.  The request parameters as normalized in Section 3.4.1.3.2, after
       being encoded (Section 3.6).

Future topic

上述過程只討論了client端的流程,server端的實現可參見:

Client/Server code

https://github.com/leah/python-oauth/

https://github.com/brosner/python-oauth2

DB Design

http://stackoverflow.com/questions/4534337/what-is-the-recommended-database-structure-for-oauth-provider

http://oauth.riaforge.org/

Reference

beginners guide: beginners-guide-to-oauth-part-iii-security-architecture

guide: http://hueniverse.com/oauth/guide/intro/

oauth1.0 spec: rfc5849 spec

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章