第87天: OAuth2.0 簡介

by 太陽雪

我們經常看到或者用到一些可以使用微博、微信、支付寶等賬號登錄的應用,還有一些微博助手、微信公衆號助手、客戶端之類的東西,這些是怎麼做的呢,背後的原理是什麼呢?爲什麼公衆號配置起來那麼繁瑣呢?什麼是 access token、refresh token?等等,今天我們來了解下開放式授權模式 OAuth

隨着互聯網的發展,各種應用相互交叉,到處需要用戶登錄,信息安全成爲了不可迴避的問題,應用需要擴展,用戶需要更好的體驗,信息需要更安全的保障,爲了滿足這些需求,互聯網技術不斷推陳出新,從通信安全,到各種協議框架,有無數的解決方案。

其中 OAuth 框架是很閃耀的一個,一經推出,就得到各大互聯網公司的積極響應,到2010年推出了 OAuth 2.0, 不但修補了 1.0 的安全漏洞,而且簡化了授權流程,得到更廣泛的應用,成爲了主流。從 PC 到 Web,從移動端到物聯網,越來越多的應用構建在 OAuth 框架之上,那麼 OAuth 是什麼呢?

OAuth 是什麼

OAuth 框架提供了一種認證和授權機制,可以讓用戶將其受保護的資源授權給其他應用來訪問或者使用。

阮一峯老師對 授權有個形象比喻:授權機制相當於你給快遞員一個臨時密碼(授權),快遞員可以使用這個密碼打開小區門禁,將快遞送到你家門口,而後零時密碼將失效(詳見參考鏈接)。

這個例子中,你就是 用戶,小區是 受保護的資源,快遞員是其他應用(第三方應用)。

如果沒有這個機制:

  • 要麼你就得去小區門口拿快遞,不方便,
  • 要麼就得告訴所有可能給你送快遞的快遞員門禁密碼,不安全

有了 OAuth 框架(協議),既方便,又安全

OAuth2.0

這裏不打算介紹 OAuth 1.0,原因是:

  • OAuth 1.0 存在安全漏洞
  • OAuth 1 和 後面的 OAuth 1a 交流流程比較複雜
  • OAuth 2.0 安全性好,應用更廣泛

如果想了解更多關於 OAuth 的知識,請訪問參考鏈接

角色

OAuth2.0 實際上就是讓第三方服務獲得用戶在資源服務器上的授權的過程,會涉及到 4 種角色

  • 資源擁有者(Resource owner),即用戶
  • 認證服務器(Authorization server),用來認證用戶憑證,頒佈授權碼的服務器
  • 資源服務器(Resource Server),存放用戶受保護的資源的服務器
  • 第三方應用(Client),也稱之爲客戶端(後續皆稱 客戶端),需要得到用戶授權,以便訪問用戶受保護的資源的應用程序

不是任何客戶端都能得到授權的,在開通 OAuth 授權之前,需要先到認證服務器或者資源服務器上註冊,註冊成功會得到 appidapp_secret,用來向認證服務器表明應用的身份

角色之間關聯

瞭解了 OAuth2.0 框架中的主要角色,有必要了解下角色之間關聯關係

  • 認證服務器 和 資源服務器:
    通常來說,認證服務器和資源服務器同屬於一個服務商,它們就有天生的關聯,而且是內部的安全的,甚至它們可以部署在同一個服務器(Web 服務器)上
  • 用戶 和 服務商:
    對於像 Github、微信這樣的知名應用,用戶會主動在這些應用或服務上註冊,填寫的資料信息,設置的暱稱,產生的文章、上傳的照片,等等將成爲用戶的資源,這些資源被存放在資源服務器上
  • 客戶端 和 服務商:
    客戶端,即第三方應用,要從服務商的資源服務器中獲取數據,給用戶提供額外服務,必須在服務商處註冊,提供應用的基本信息,認證信息,服務域名,申請用戶授權的範圍、甚至企業資質(例如申請微信公衆號的企業服務)等等,申請通過後,服務商會返回 appidapp_secret,作爲客戶端和服務商的交互憑證
  • 用戶 和 客戶端:客戶端提供了特別的服務,可以吸引到用戶,爲了讓用戶體驗更好,引導用戶通過授權的方式,從而獲取授權範圍內的用戶信息,例如 Openid,作爲用戶在客戶端上的唯一標識,從而建立起和用戶的關聯

至此,四個角色之間的關聯就建立好了,下面開始介紹具體的授權方式

基本授權流程

沒有比圖更能說明白流程的,借用 RFC6749 文檔中的圖:

授權流程圖

  • A 客戶端,向用戶發出授權請求
  • B 用戶同意或者拒絕客戶端的授權請求,假設是同意
  • C 客戶端拿着用戶的授權請求認證服務器做認證
  • D 如果 C 通過認證,認證服務器將返回 Access Token,即可以訪問資源的令牌
  • E 客戶端使用 Access Token 請求資源服務器上的資源
  • F 資源服務器驗證了 Access Token 後,返回受保護的資源

流程中最核心的是讓客戶端獲得 Access Token,之後在訪問受保護資源是,就不需要用戶反覆授權了

Access Token 顯然不是用戶在資源服務器上的密碼,是有認證服務器頒發的,那麼也可以被銷燬

Access Token 和之前課程中的 JWT 是類似的,實際上 JWT 是 OAuth 認證的一個特例

授權模式

根據授權流程,OAuth2.0 定義了 4 種針對不同應用場景的授權模式

  • 授權碼模式(authorization code)
  • 簡化模式(implicit)
  • 密碼模式(resource owner password credentials)
  • 客戶端模式(client credentials)

授權碼模式

授權碼模式是最完整,安全性最高的授權模式,也是最常用的一種模式,其特點是通過客戶端的後臺服務器與認證服務器交互,如圖:

授權碼模式流程圖

注意:上圖中的步驟 A, B, C 在通過用戶代理端( User-Agent 一般指瀏覽器)時,被拆分成了兩部分

  • A 用戶訪問客戶端的客戶端,後者將前者導向認證服務器
  • B 用戶確定是否授權給客戶端
  • C 假設用戶給予授權,認證服務器將用戶導向客戶端事先指定的"重定向URI"(Redirection URI),同時附上一個授權碼
  • D 客戶端收到授權碼,通過後臺服務器,附上早先的"重定向URI",向認證服務器申請令牌。這一步對用戶不可見
  • E 認證服務器覈對了授權碼和重定向URI,確認無誤後,向客戶端發送訪問令牌(access token)和更新令牌(refresh token)

接下來說明一下過程中所包含一下參數

不同認證服務器上的參數名稱有可能不同,但含義相同,例如 client_id 一般被 appid 代替

步驟 A,客戶端申請認證的 URI,包含以下參數:

  • response_type:表示授權類型,必選項,此處的值固定爲 code,因爲需要先獲取授權碼
  • client_id:表示客戶端的ID,必選項,是在認證服務器分配給客戶端的id,即 appid
  • redirect_uri:表示重定向URI,可選項
  • scope:表示申請的權限範圍,可選項
  • state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值

步驟 C,認證服務器迴應的 URI,包含以下參數:

  • code:表示授權碼,必選項。該碼的有效期應該很短,通常設爲 10 分鐘,客戶端只能使用該碼一次,否則會被認證服務器拒絕。該碼與客戶端 ID 和重定向 URI,是一一對應關係
  • state:如果客戶端的請求中包含這個參數,認證服務器的迴應也必須一模一樣包含這個參數

步驟 D,客戶端向認證服務器申請令牌的 HTTP 請求,包含以下參數:

  • grant_type:表示使用的授權模式,必選項,此處的值固定爲 authorization_code
  • code:表示上一步獲得的授權碼,必選項
  • redirect_uri:表示重定向 URI,必選項,且必須與 A 步驟中的該參數值保持一致
  • client_id:表示客戶端 ID,必選項

步驟 E,認證服務器發送的 HTTP 響應,包含以下參數:

  • access_token:表示訪問令牌,必選項
  • token_type:表示令牌類型,該值大小寫不敏感,必選項,可以是bearer類型或mac類型
  • expires_in:表示過期時間,單位爲秒。如果省略該參數,必須其他方式設置過期時間
  • refresh_token:表示更新令牌,用來獲取下一次的訪問令牌,可選項
  • scope:表示權限範圍,如果與客戶端申請的範圍一致,此項可省略

認證服務器會以 JSON 的形式返回 access_token 數據,且不允許做緩存,以提高安全性

簡化模式

簡化模式不需要通過客戶端後臺服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了授權碼這個步驟,因此得名。所有步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認證,如圖:

簡化模式流程圖

  • A 客戶端將用戶導向認證服務器
  • B 用戶決定是否給於客戶端授權
  • C 假設用戶給予授權,認證服務器將用戶導向客戶端指定的重定向URI,並在URI的Hash部分包含了訪問令牌 access_token
  • D 瀏覽器向資源服務器發出請求,其中不包括上一步收到的Hash值
  • E 資源服務器返回一個網頁,其中包含的代碼可以獲取Hash值中的令牌
  • F 瀏覽器執行上一步獲得的腳本,提取出令牌
  • G 瀏覽器將令牌發給客戶端

接下來說明一下過程中所包含一下參數

步驟 A,客戶端發送 HTTP 請求,包含的參數:

  • response_type:表示授權類型,此處的值固定爲 token,必選項
  • client_id:表示客戶端的ID,必選項
  • redirect_uri:表示重定向的URI,可選項
  • scope:表示權限範圍,可選項
  • state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值

步驟 C,認證服務器迴應客戶端的 URI,包含以下參數:

  • access_token:表示訪問令牌,必選項。
  • token_type:表示令牌類型,該值大小寫不敏感,必選項
  • expires_in:表示過期時間,單位爲秒。如果省略該參數,必須其他方式設置過期時間
  • scope:表示權限範圍,如果與客戶端申請的範圍一致,此項可省略
  • state:如果客戶端的請求中包含這個參數,認證服務器的迴應也必須一模一樣包含這個參數

有個需要注意的地方,步驟 C,返回的 access_token 放在重定向 URL 的 Fragment 中,即錨點中, # 後面,例如

http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
  &state=xyz&token_type=example&expires_in=3600

因爲錨點中的內容不會發送給後臺,從而減少了一次數據傳輸,降低了一定風險

對於簡化模式獲得的 access_token 有效期很短,一般是會話級的,即當會話結束時就失效

密碼模式

密碼模式中,用戶向客戶端提供自己的用戶名和密碼,客戶端使用這些信息,向"服務商提供商"索要授權。

在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼(既然用戶信任你,你就必須兌現這個承諾)。

密碼模式的特性決定,需要用在用戶對客戶端高度信任的情況下,比如客戶端是操作系統的一部分,或者由一個著名公司出品,而認證服務器只有在其他授權模式無法執行的情況下,才能考慮使用這種模式

這裏只簡單介紹下,不做做詳細講解,如有興趣瞭解,可以查閱文末參考

客戶端模式

客戶端模式指客戶端以自己的名義,而不是以用戶的名義,向"服務提供商"進行認證。嚴格地說,客戶端模式並不屬於 OAuth 框架所要解決的問題

在這種模式中,用戶直接向客戶端註冊,客戶端以自己的名義要求"服務提供商"提供服務,其實不存在授權問題

客戶端模式,就像二道販子(只爲借用比喻,並無貶義),將原始服務包裝後,再提供給最終用戶,常見於多租戶的 Saas 系統,例如統一提供支付通道、處理 GPS 信息等

這裏也只簡單介紹下,如有興趣瞭解,可以查閱文末參考

刷新 access_token

在 授權碼模式中,授權服務器可以會同時返回 refresh_token,用來在 access_token 過期前,重新獲取新的 access_token,不需要用戶重新確認授權,有助於提高用戶體驗

在 access_token 過期前,客戶端可用 refresh_token 想授權服務器發送請求,例如,假設 b.com 是授權服務器地址,請求大體是:

https://b.com/oauth/token?
  grant_type=refresh_token&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET&
  refresh_token=REFRESH_TOKEN
  • grant_type: 授權類型,值爲 'refresh_token'
  • client_id: 客戶端 id,即第三方應用在授權服務器上註冊被分配的 id
  • client_secret: 客戶端和授權服務器通行的密鑰,有授權服務器頒發,在特殊需要確認的情況下需要作爲驗證條件
  • refresh_token: 用戶獲取新的 access_tokenrefresh_token

安全的 OAuth2.0

上面較爲詳細的講述了 OAuth2.0 框架,瞭解了在開放網絡中如何安全的獲取用戶授權的技術細節,但再完善的交互方案、再複雜的嚴密的通信過程,都避免不了中間人攻擊,當客戶端和認證服務器之間通過 http 協議交互數據時,會被截取通信內容,從而獲得用戶的授權,這是不能接受的,所以 OAuth2.0 需要建立在 https 協議上,將通信內容加密,最大程度的防止信息被竊取。

如果 OAuth2.0 框架用在敏感信息交互上時,必須使用 https 協議確保安全,但並不是說只能支持 https,對於非敏感數據,或者不重要的授權,可以使用 http 協議作爲通信方式

總結

本節課程着重介紹了 OAuth2.0 授權框架,從它的作用,到具體的技術細節,做了較爲詳細的講述,如果需要用安全的授權,需要將通信建立在 https 協議之上。由於 OAuth 概念較多,流程複雜,這節沒有涉及到具體的編程實踐,下一節,我們以 Github 爲例,使用之前介紹過的 Authlib 模塊,用 Flash 實現一個第三方應用,作爲實踐,敬請期待

參考

關注公衆號:python技術,回覆"python"一起學習交流

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