[OAuth Series] OAuth 的各式參數說明

OAuth 使用上最難懂以及測試的,莫過於這些 OAuth 的參數,尤其是在 OWASP 的 Web Security Report 之下,又有 Improper Error Handling 的安全漏洞問題,因此在測試 OAuth 時,最容易吃的苦頭就是只知道 HTTP 400 (Bad Request) 或 HTTP 401 (Unauthorized),有些服務還會提供一些錯誤訊息,但也有一點都不提供的,而且就算有提供,也不一定馬上就可以意識到問題在哪 (ex: Signature Invalid) … 往往都要做很多的實驗才能真正找到問題在哪,我在測試 Twitter 的 OAuth 時就吃了很多的苦頭… Orz。

OAuth 使用上最難懂以及測試的,莫過於這些 OAuth 的參數,尤其是在 OWASP 的 Web Security Report 之下,又有 Improper Error Handling 的安全漏洞問題,因此在測試 OAuth 時,最容易吃的苦頭就是只知道 HTTP 400 (Bad Request) 或 HTTP 401 (Unauthorized),有些服務還會提供一些錯誤訊息,但也有一點都不提供的,而且就算有提供,也不一定馬上就可以意識到問題在哪 (ex: Signature Invalid) … 往往都要做很多的實驗才能真正找到問題在哪,我在測試 Twitter 的 OAuth 時就吃了很多的苦頭… Orz。

我們再以下圖來列出 OAuth 會使用到的參數:

 

  • oauth_consumer_key:這是由服務所提供的應用程式金鑰,要在每次 HTTP Request 中附加到 Authorization 標頭中。
  • oauth_consumer_secret:這是由服務提供的應用程式簽章金鑰,會用來計算 siguature 用。
  • oauth_token:由服務在驗證後,核發的 Request Token 或 Access Token,要在每次 HTTP Request 中附加到 Authorization 標頭中。
  • oauth_token_secret:由服務驗證後,核發的簽章金鑰,會和 oauth_consumer_secret 一起用來計算 signature 用。
  • oauth_timestamp:由 UTC 時間 1970/1/1 00:00:00 起到當下時間所經過的秒數,但也有一些開發人員使用 64 位元的隨機數字來代用。
  • oauth_nonce:64 位元的隨機字串 (64bit random string),這個說法不容易懂,不過可以直接由 oauth_timestamp 轉換而得。
  • oauth_signature_method:決定 signature 使用的演算法,目前 OAuth 1.0 中定義了 HMAC-SHA1,RSA-SHA1 以及 PLAINTEXT 三種格式,但一般會使用 HMAC-SHA1 較多,Google OAuth Playground 預設的演算法是 RSA-SHA1。
  • oauth_signature:這是最容易出錯的一項資料,它會基於三個階段的 Request 資料,使用 oauth_signature_method 決定的演算法,使用 oauth_consumer_key 以及 oauth_token_secret 計算的簽章值,但如果 Request 的資料有誤時,signature 簽章值也會錯誤,而且不易除錯(參數順序錯誤也不行…)。
  • oauth_version:指定 OAuth 的版本值,目前為 1.0。
  • oauth_verifier:在 Verifier 階段時,由服務核發的檢核碼。
  • oauth_callback:由用戶端應用程式設定,服務回呼時使用的網址,若應用程式是 Desktop Application 時,此值可設為 oob (Out-Of-Box),此時服務會用不同的方式來進行使用者授權階段。

這些參數中最需要提的,莫過於 oauth_signature 了,它需要先取得 Request 的參數資料,再用 consumer key 和 token secret 進行雜湊計算 (使用 HMAC-SHA1 或是 RSA-SHA1 演算法) 後產生的簽章值。Request 參數資料被稱為基礎字串 (base string),基礎字串是由 HTTP Method, Request URL 以及 Normalized Parameters 組合,它的格式是  {HTTP_METHOD}&{URL}&{PARAMETERS},HTTP Method 可以是 GET 或 POST,URL 會隨要求不同而所有不同,而 Normalized Parameters 是一種正規化的參數清單,它要符合兩個條件:

  1. 必須要是 Lexicographical byte order 的順序,簡單的說,就是要以字母順序判斷排序,如果在參數中的 key 值順序相同時,就要比對 value 值。
  2. 每個參數都要以 key=value 方式組合。
  3. 每個值都要經過 UrlEncode() 處理過,這個 UrlEncode() 是一個特別的版本,我們在程式設計時再說明。

例如 Request Token 階段,必須要有 oauth_consumer_key, oauth_signature_method, oauth_version, oauth_callback, oauth_nonce, oauth_siguature 與 oauth_timestamp 等參數,在處理 Normalized Parameters 時,則一定要使用下列順序排序:

  • oauth_callback=xxx
  • oauth_consumer_key=xxx
  • oauth_nonce=xxx
  • oauth_signature_method=xxx
  • oauth_timestamp=xxx
  • oauth_version=xxx

而 Normalized Parameters 也規定,不能包含 oauth_signature,所以參數中不可以有 oauth_signature。下列字串就是 base string 的範例(有分行,真實的情況是一整行):

POST&
https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&
oauth_callback%3Dhttp%253A%252F%252Flocalhost%253A3005%252Fthe_dance%252Fprocess_callback%253Fservice_provider_id%253D11%26
oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3DQP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk%26
oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323042%26oauth_version%3D1.0

 

在 base string 組合出來後,即可使用 .NET 的 System.Security.Cryptographics 命名空間中的 HMACSHA1 類別,使用 ComputeHash() 計算簽章值,並設定至 oauth_siguature 參數,作為 OAuth 驗證訊息的簽章之用。

說完這些基本知識後,我們下一回開始進入程式設計的階段。