文章来源:
http://blog.yorkxin.org/posts/2013/09/30/oauth2-implementation-differences-among-famous-sites/
September 30, 2013 · 1 Comment
因為我現在要自己做 OAuth 2 的服務,所以當然要先看一下別人怎麼做。
然而,即使 OAuth 2.0 的 spec 規定了很多通訊協定上的實作細節,但現實總是跟理想有所差距,各大網站的 OAuth 2 實作都或多或少與 spec 有差異,真正完全照 spec 來做的很少(功能閹割的不算數)。不過概念上都符合 OAuth 2 ,只是實作上有差。
我去看了以下這些網站的 OAuth 2 API 文件,清單是從 找來的。為了排版美觀, Grant Type 的 Authorization Code 簡寫成 Auth Code, Client Credentials 簡寫成 Client Cred.,Resource Owner Password 簡寫成 Password。檢閱日期是 2013 年 9 月 27 日,未來各 API 可能會改變,導致下表的情況跟現況不一致。
Service
|
spec
相容
|
支援的 Grant Types
|
scope
分隔
|
Refresh
Token
|
Client 認證
|
Facebook
|
?
|
Auth Code, Implicit, Client Cred.
|
comma
|
△ (自製)
|
GET
|
GitHub
|
?
|
Auth Code, Password (自製)
|
comma
|
?
|
POST
|
Twitter
|
?
|
Client Cred.
|
(無 scope)
|
?
|
Basic
|
Google
|
?
|
Auth Code, Implicit
|
space
|
?
|
POST
|
|
?
|
Auth Code, Implicit
|
???
|
?
|
POST
|
Dropbox
|
?
|
Auth Code, Implicit
|
(無 scope)
|
?
|
Basic, POST
|
Amazon
|
?
|
Auth Code, Implicit
|
space
|
?
|
Basic, POST
|
Bitly
|
?
|
Auth Code (半自製), Password
|
(無 scope)
|
?
|
POST (Auth Code),
Basic (Password)
|
|
?
|
Auth Code
|
comma
|
?
|
Basic, GET
|
豆瓣
|
?
|
Auth Code, Implicit
|
comma
|
?
|
POST
|
BOX
|
?
|
Auth Code
|
(無 scope)
|
?
|
POST
|
|
?
|
Auth Code
|
(無 scope)
|
?
|
POST
|
大概總結一下:
關於 Endpoints:
-
GitHub 和 Basecamp 省略了 response_type 和 grant_type ,猜測是因為只有一種流程。但一樣情況的 Twitter 、 BOX 、新浪微博,則依然要傳 switch 參數。
-
通常 Authorization Endpoint 都是跟主站放在一起的,而不是放在 API 裡面,我想這個目的是要讓 User 直接用 cookie 登入並授權。
關於 Grant Types:
-
幾乎大家都至少會支援 Authorization Code Grant (Twitter 不支援)。
-
適合實作第三方登入的尤其會支援 Implicit 來做無縫接入(新浪微博似乎是個例外)。
-
Client Credentials 很少有人會支援(Twitter 用來給 App 存取「非代表使用者」的資料)。
-
Resource Owner Password 很少有人支援。GitHub 有一種類似的用法,但不是照規格,而是一種自製的流程。
-
除了內建的四種 Grant Types ,某些服務還會設計自己的 Grant Type,像是 Microsoft 就有一個叫 Sing-In Control Flow ,是 Implicit 的一種變體。
關於 Client Authorization (認證):
-
大部份都有支援 POST
-
並非全部都有支援 HTTP Basic Auth ,但規格書裡面規定的是要至少支援 Basic Auth ,因為這一點,所以我把很多個服務標成「不相容 spec」
-
少數有使用 GET
關於資料格式:
-
space 的分隔符 (delimiter) 很多用 , 逗號 (comma) ,照規格書用空格 (space) 的也有,不過還有完全不存在 "scope" 的概念,授權範圍就是完全存取。
-
Microsoft 的 delimiter 我不知道到底是用什麼,詳情見下文。
-
Token Type 雖然不是每個都是 "Bearer" ,但基本上概念都接近。目前沒有看到使用 MAC Token 的。
其他:
-
Refresh Token 不是大家都有支援。
-
某些服務會提供 SDK ,像是 Facebook 、新浪微博,這樣子在網頁、手機上面,不需要手動規劃流程,由 SDK 完成,這樣也可以防止 App 在流程中動手腳,偷走密碼之類的資料。
以下各服務的筆記。
Facebook
文件: https://developers.facebook.com/docs/facebook-login/login-flow-for-web-no-jssdk/
Grant Types
-
Authorization Code
-
Implicit
-
Client Credentials (用來取得 App Access Token)
Endpoints
-
Authorization Endpoint: (非 graph.facebook.com)
-
Token Endpoint:
特色
-
概念上跟 OAuth 2 雷同,但沒有完全照標準。
-
scope 用逗號 , 分隔 (非標準)
-
Client Authentication 用 GET (非標準)
-
Authorzation Endpoint 有提供同時拿 Authorization Code 和 Access Token 的功能(我不清楚是什麼用途)
-
Implicit Flow 在使用 Token 之前,建議 validate ,防偽造攻擊。詳見 Confirming Identity 段落。
-
Token 分成很多種,分別有不同的用途。詳見 Access Tokens。
-
Desktop App 的 Redirection URI 固定為 ,並要求開發者內嵌一個 browser (如 WebView),監視其 state change 來取得 Access Token。
-
有自己的 Token Refresh 機制,見 Re-authentication。
-
Token Type 不是 Bearer Token,但用起來很像。
其他值得參考的文件:
關於固定的 Redirection URI
前面提到說它的 Redirection URI 固定為 ,這個 URI 我覺得很有意思,打開來是這樣的內容:(斷行是我自己加的,原文沒斷行)
Success
/> style="color:red">安全警告:請以保護密碼的相同態度處理以上網址,切勿和任何人分享。
看這段 JavaScript,用途是「500ms 之後自動把瀏覽器的歷史記錄消滅掉,並且讓現在網址變成 blank.html#_=_」。這是什麼用途呢?
我猜測搭配 Implicit Grant Flow 用的。在 Implicit Grant Flow 裡面, Access Token 會包在 Fragment 裡面(就是網址最後面的那個 #xxxx),這樣子一來會被 User-Agent 放進歷史記錄裡,二來如果人眼看得到這個 User-Agent 的 Location Bar ,就可以看到 Access Token 。
所以 Facebook 推薦給 Desktop App 的實作方式,就是程式監視內嵌的 User-Agent 的當前網址,看到這個固定的 Redirection URI ,就可以抓 Access Token 了。而不管有沒有抓到,網頁裡的 script 都會把 Access Toekn 消除掉。
又,這種 #_=_ 也常常在 Facebook 第三方登入的時候看到,我猜測也是基於相同的原因,不過還沒有證實。
GitHub
文件: http://developer.github.com/v3/oauth/
Grant Types
-
Authorization Code
-
Resource Owner Password (自製,非標準)
Endpoints
用於 Authorization Code:
-
Authorization Endpoint:
-
Token Endpoint:
Resource Owner Password Grant Flow 是自製的流程,叫做 Authorizations,用的是 RESTful API,不是直接套用 OAuth 標準。在 Grant 的時候不使用上述的 Endpoints。
特色
-
scope 用 , 逗號區隔(非標準)
-
Client Authentication 支援 POST Auth (非標準)
-
所謂「自製的 Resource Owner Password Grant Type」,我指的是 GitHub 另外提供「讓 Resource Owner 自行管理 Authorizations」的 API ,見 OAuth Authorizations API 段落。
-
因為 Endpoint 只需要支援 Authorization Code Grant ,所以省略了 respose_type 和 grant_type。
-
沒有 Refresh Token
-
Token 沒有時效,亦即除非手動 revoke ,否則永遠有效。
-
Token Type 不是 Bearer Token,但用起來很像。
GitHub.app 即是使用 OAuth
GitHub 的 Mac GUI 應用程式就是用 OAuth 來存取資料的。你可以打開 Keychain Access ,找到 "github.com/mac ()" 這個項目,按 Show Password 就可以看到 OAuth Access Token 了:
用同樣的 Access Token 可以 call API:
Terminal
$ curl -i -H "Authorization: token bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXb"
HTTP/1.1 200 OK
Server: GitHub.com
X-OAuth-Scopes: notifications, repo, user
X-Accepted-OAuth-Scopes: user, user:email, user:follow, site_admin
X-GitHub-Media-Type: github.beta
X-Content-Type-Options: nosniff
# 部份略
{
"login": "chitsaou",
"id": 10737
(略)
}
Twitter
文件: https://dev.twitter.com/docs/auth/application-only-auth
Grant Types
Endpoints
特色
-
與 spec 相容
-
只准用在 Application-only Path ,即是「代表 App 操作」。如果要「代表 User 操作」,則必須走 OAuth 1.0a 的流程。見 OAuth Signed 文件。
-
Client Authentication 用 Basic Auth (標準)。
-
Access Token 使用 Bearer Token 標準 (RFC 6750) 。
-
沒有 Refresh Token
-
Access Token 沒有時效,但文件裡提及 app credentials 會過期,這個我搞不懂。(原文是 Obtain or revoke a bearer token with incorrect or expired app credentials)
-
用 Bearer Token (RFC 6750)
Google
文件: https://developers.google.com/accounts/docs/OAuth2
Grant Types
-
Authorization Code
-
Implicit
還有一種 Grant Flow 叫做 "for Devices" ,這是專門為 User-Agent 功能很少的設備來設計的,例如遊戲機、印表機。
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
-
scope 用空白分隔。(標準)。
-
Client Authentication 用 POST (非標準)。
-
特別提到 Authorization Code Grant Flow 適用 Chrome App
-
特別提到 Implicit Grant Flow 最好 validate token (同 Facebook)
-
把 Native App 歸類在「使用 Authorization Code Grant Flow」裡面,但如此一來 secret 就不再是 secret ,會被抓出來。
-
對於 Native App,預設有一個 Redirection URI 叫做 urn:ietf:wg:oauth:2.0:oob 。跟 Facebook 的 Desktop App 指南一樣,這是可以給內嵌 browser 監視其 state change 來取得 Access Token 的方式。見 Using OAuth 2.0 for Installed Applications / Choosing a Redirect URI
-
有 Refresh Token
-
用 Bearer Token (RFC 6750)
Microsoft (Windows Live)
文件:
Grant Types
-
Authorization Code Grant
-
Implicit
-
Sign-in Control (自製,從 Implicit Flow 變化來的,本文略)
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
-
scope 分隔不明。(沒明說,照文件的是空格,但 卻是逗號)
-
Client Authentication 用 POST (非標準)。
-
在 Authorization Code Grant Type Flow 裡面,可以自行指定 App 為 Desktop 或 Mobile ,這樣子 Redirection URI 會固定為。跟 Facebook 的 Desktop App 指南一樣,要求開發者內嵌一個 browser (如 WebView),監視其 state change 來取得 Access Token。不過跟 Facebook 不同的是,它裡面打開是空空如也,沒有 script 來把 access token 藏起來。
-
有 Refresh Token
-
Access Token 沒有時效,但文件裡提及 app credentials 會過期,這個我搞不懂。(原文是 Obtain or revoke a bearer token with incorrect or expired app credentials)
-
Token Type 沒明說,但看起來也不是 MAC Token ,而是類似 Bearer Token。
Dropbox
文件: https://www.dropbox.com/developers/core/docs
Grant Types
-
Authorization Code
-
Implicit
Endpoints
-
Authorization Endpoint: (非 api.dropbox.com)
-
Token Endpoint:
特色
-
與 spec 相容
-
沒有 scope 的概念
-
Client Authentication 支援 Basic Auth 和 POST Auth
-
用 Bearer Token (RFC 6750)
Amazon
文件: 裡面的一份 PDF
Grant Types
-
Authorization Code
-
Implicit
Endpoints
-
Authorization Endpoint: (非 api.amazon.com)
-
Token Endpoint:
特色
-
與 spec 相容
-
scope 用空格分隔(標準)。
-
Client Authentication 支援 Basic Auth 或 POST (標準)。
-
特別提到 Implicit Grant Flow 最好 validate token (同 Facebook)
-
有 Refresh Token
-
使用 Bearer Token (RFC 6750)。
另外文件裡面還提到安全性問題 (Security Considerations),是從 Spec 的 Security Considerations 來的,但比 spec 的好讀……。
其中我特別注意到的幾點:
-
CSRF - 建議把 state 用 HMAC 編碼過,其 secret 就是 client secret 。
-
Implicit Flow 的 Resource Owner 偽裝 - 建議要向 Server 驗證 Access Token。
-
Open Redirector - 最好不要在 Redirection Endpoint 裡面放 &url=xxx 這種東西。
-
Code Injection - 最好把 state 驗證過沒問題再拿來用,顧客資料 (customer profile) 也要如此做。
Bit.ly
文件: http://dev.bitly.com/authentication.html
Grant Types
-
Authorization Code (部份自製,非標準)
-
Resource Owner Password
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
Bit.ly 的情況比較特別,它雖然有 Authorization Code Grant Flow ,但實作的細節卻跟 OAuth 2.0 有點不同,這個不同就導致它與 spec 不相容:
-
發 Access Token 不用 JSON 而是用 URL-encoded string (但 Password Grant 卻是用 JSON)。
-
Client Authentication 用 POST 而不是 Basic Auth (但 Password Grant 卻是用 Basic Auth 而不是 POST)。
其他特色:
-
沒有 scope 的概念。
-
Client Authentication 用 Basic Auth (Password Grant)或 POST (Auth Code Grant),互相不能交換。
-
沒有 Refresh Token
-
Token Type 沒有明說是哪一種。
新浪微博
文件:
Grant Types
-
Authorization Code
-
Implicit
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
-
scope 用逗號 , 分隔(非標準)。
-
Client Authentication 用 Basic Auth(標準)和 GET。
-
有 Refresh Token
-
有 Token 自動展期機制。
-
Token Type 不是 Bearer Token。 Call API 的時候可以用 GET 或 Header 送 token。
-
有對 Client 分等級,不同等級有不同的 Rate Limiting 和 Token 時效。
另外它還提供了這份文件可以參考,雖然是從 Spec 裡面的 Security Considerations 拉出來的。
豆瓣
文件: http://developers.douban.com/wiki/?title=oauth2
Grant Types
-
Authorization Code
-
Implicit
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
-
scope 用逗號 , 分隔(非標準)。
-
Client Authentication 用 POST (非標準)。
-
有 Refresh Token
-
用 Bearer Token (RFC 6750)。
-
有對 Client 分等級,不同等級有不同的 Rate Limiting 和 Token 時效。
-
Error Response 是自己設計的標準,有自己定義錯誤代碼表,其中不少是直接從 OAuth 2.0 Spec 來的。
BOX
文件: http://developers.box.com/oauth/
Grant Types
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
-
沒有 scope 的概念。
-
Client Authentication 用 POST (非標準)。
-
有 Refresh Token
-
使用 Bearer Token (RFC 6750)。
-
對於「禁止轉回 Redirection Endpoint」的錯誤情況,會出現一個精美的頁面來提示錯誤。
-
有 self-revoke 的流程。
Basecamp (37signals)
文件:
Grant Types
Endpoints
-
Authorization Endpoint:
-
Token Endpoint:
特色
-
沒有 scope 的概念。
-
Client Authentication 用 POST (非標準)。
-
有 Refresh Token
-
用 Bearer Token (RFC 6750)。
-
改密碼就會直接 revoke Access Tokens 。
阅读(1727) | 评论(0) | 转发(0) |