OAuth2是基於HTTP的認證API,一般與OAuth2搭配的API也是基於HTTP的REST風格API(比如新浪微博和github),很多人一定想過是否可以直接從瀏覽器端調用REST API。
我最近做了一些這方面的研究,因為OAuth2中有secret key的存在,所以純粹的客戶端是不行的,但是服務端僅僅參與認證過程,由瀏覽器去調用REST API則是完全可行的。
於是比如你想開發一個github應用,那么服務端只需要一個沒有界面的Auth服務就可以了,大部分的工作可以讓瀏覽器端完成,這個架構可以大大減輕服務器的壓力,對於不熟悉后端語言的前端工程師來說,是個不錯的選擇。
首先傳統的oauth過程是這樣的:
首先由跳轉到OAuth服務器的登錄認證頁面,進行登錄或者授權(假如已經在別的地方登錄,就只需要授權):
然后服務端通常會返回302跳轉到一個帶ticket參數的網址,這個網址一般是在OAuth服務器注冊的地址,也有些OAuth允許客戶端指定:
這樣瀏覽器端拿到302后,會自動轉到App服務器,因為請求的Query String里面帶了ticket,App Server於是拿到了ticket。客戶端對App Server的請求是非Https,這個ticket是不怕被截獲的,因為ticket是一次性的,而且攻擊者拿到了ticket沒有secret key是沒法去Oauth服務器騙取token的:
App Server再對Oauth Server發HTTP請求,帶上Secret Key:
OAuth服務器會把access_token傳給App Server:
原本如果只用服務端訪問REST API,這個token保存在服務端就可以了,但是我們現在希望直接在瀏覽器端用XHR去訪問REST API,所以我們必須把token傳給瀏覽器端。
這時候問題出現了,對於大部分開發者而言,花錢買個證書走https是不現實的,而http請求中明文傳遞token是可能被截獲的:
token中包含用戶授權信息,只要黑客截獲了token,就可以冒充用戶身份去Oauth服務器為所欲為:
解決的辦法是使用RSA在瀏覽器端生成一對RSA密鑰,然后把公鑰傳給App Server(建議用cookie,非常方便),Server用公鑰加密token后傳回給客戶端。
我使用的是斯坦福大學的RSA開源實現(這個真的是非常高質量的RSA實現,向斯坦福師生致敬)
http://www-cs-students.stanford.edu/~tjw/jsbn/
學者們的實現比較文藝,依賴關系稍微有些復雜,這里我把所有文件打了個包,方便大家下載:
over,接下來在瀏覽器端去使用token吧。
github API 的一個開源實現,請看 https://github.com/wintercn/github.wind