1. 程式人生 > >OAuth認證

OAuth認證

地址 分包 如果 網站 p s noi con 提供服務 跨站

https://www.wuhuachuan.com/visitor/learning/article/getArticleDetail?id=e70818e5-f5f1-4640-b928-f908bece0463&utm_source=tuicool&utm_medium=referral

前言

主要想總結下工作中使用的 Kong 集成 OAuth 這項技術,所以轉載這篇文章先介紹 OAuth 的一些概念。如果有時間,還是讀一下 OAuth RFC 文檔好: 點這裏

OAuth 概念

OAuth 是一個開放標準,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯系人列表), 而不需要將用戶名和密碼提供給第三方應用。

OAuth允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。 每一個令牌授權一個特定的網站在特定的時段內訪問特定的資源。 這樣,OAuth讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容。

OAuth 運行流程

首先會有幾個術語:

  • Resource owner : 資源所有者,本文中稱為 “用戶”。
  • Authorization server :認證服務器,即服務提供商專門用來處理認證的服務器。
  • Resource server:資源服務器,即用戶提供商存放用戶生成的資源的服務器。它和認證服務器,可以是同一臺服務器,也可以是不同的服務器。

總的來說, 認證服務器 和 資源服務器 都由 服務提供商 提供。流程如下圖:

技術分享

文字解釋:

  • 用戶打開客戶端以後,客戶端要求用戶給予授權。
  • 用戶同意給予客戶端授權。
  • 客戶端使用上一步獲得的授權,向認證服務器申請令牌。
  • 認證服務器對客戶端進行認證後,確認無誤後,同意發放令牌。
  • 客戶端使用令牌,向資源服務器申請獲取資源。
  • 資源服務器確認令牌無誤後,同意向客戶端開放資源。

上面的 6 個步驟中,重點在於 2 ,即用戶怎麽給客戶端授權,有了這個授權,客戶端就可以獲取令牌,進而憑借令牌獲取資源。

OAuth 授權模式

OAuth2.0 定義了 四種授權模式。分別為:

  • 授權碼模式
  • 簡化模式
  • 密碼模式
  • 客戶端模式

授權碼 模式

授權碼模式是功能最完整,流程最嚴密的授權模式。它的特定就是通過客戶端的後臺服務器,與“服務提供商”的認證服務器進行互動。流程如下圖:

技術分享

解釋:

首先,用戶訪問客戶端,後者將前者導向認證服務器。如: https://www.example.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read

  • www.example.com/v1/oauth/authorize :API 授權的終端。
  • client_id :應用程序的client ID,用於 API 識別應用程序。
  • redirect_uri :獲得授權碼之後,服務提供商重定向用戶代理(比如瀏覽器)的地址。
  • response_type : 表明授權類型,默認是 code。即授權碼模式。
  • scope: 應用程序可以獲得的授權級別,默認值為 read。
  • state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值,用於抵禦 CSRF 攻擊。

然後,用戶選擇是否給予授權。如下圖:

技術分享

假如用戶給予授權,認證服務器將用戶導向客戶端事先指定的 “重定向URL”,同時附上一個授權碼: https://www.jianshu.com/callback?code=AUTHORIZATION_CODE

客戶端收到授權碼,附上之前的 “重定向URI” 向認證服務器申請令牌。這一步是在客戶端的後臺的服務器上完成的,對用戶不可見。

https://www.example.com/v1/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_url=REDIRECT_URL

URI 包括:

  • www.example.com/v1/oauth/authorize :API Token的終端。
  • client_id :即 app key / consumer key ,用於驗證應用程序。
  • client_secret:即 app secret / consumer secret 用於驗證應用程序。
  • grant_type :剛剛獲得的授權碼
  • redirect_uri :重定向URI,和第一步一致。

認證服務器核對了授權碼 和 重定向 URI 確認無誤後,向客戶端發送訪問令牌和 更新令牌。

{ "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope:read" }

包括了:

  • access_token:訪問令牌
  • token_type :令牌類型
  • expires_in :過期時間,單位為秒
  • refresh_token: 更新令牌,用來獲取下一次的訪問令牌。
  • scope:權限範圍。

Ps:這裏可能會有一個疑惑,為什麽要發送兩次請求得到 token,為什麽要有 code?

是這樣子的:

  1. 瀏覽器的 redirect uri 是一個不安全信道,此方式不適合於傳遞敏感數據(如 access token)。 因為 uri 可能通過 HTTP referrer 被傳遞給其它惡意站點,也可能存在於瀏覽器 cacher 或 log 文件中,這就給攻擊者盜取 access token 帶來了很多機會。 另外,此協議也不應該假設 RO 用戶代理的行為是可信賴的,因為 RO 的瀏覽器可能早已被攻擊者植入了跨站腳本用來監聽 access token。 因此,access token 通過 RO 的用戶代理傳遞給 Client,會顯著擴大 access token 被泄露的風險。 但 authorization code 可以通過 redirect uri 方式來傳遞,是因為 authorization code 並不像 access token 一樣敏感。 即使 authorization code 被泄露,攻擊者也無法直接拿到 access token,因為拿 authorization code 去交換 access token 是需要驗證 Client 的真實身份。 也就是說,除了 Client 之外,其他人拿 authorization code 是沒有用的。 此外,access token 應該只頒發給 Client 使用,其他任何主體(包括 RO)都不應該獲取 access token。 協議的設計應能保證 Client 是唯一有能力獲取 access token 的主體。 引入 authorization code 之後,便可以保證 Client 是 access token 的唯一持有人。 當然,Client 也是唯一的有義務需要保護 access_token 不被泄露。
  2. 引入 authorization code 還會帶來如下的好處。 由於協議需要驗證 Client 的身份,如果不引入 authorization code,這個 Client 的身份認證只能通過第1步的 redirect uri 來傳遞。 同樣由於 redirect uri 是一個不安全信道,這就額外要求 Client 必須使用數字簽名技術來進行身份認證,而不能用簡單的密碼或口令認證方式。 引入 authorization_code 之後,AS 可以直接對 Client 進行身份認證(見步驟4和5),而且可以支持任意的 Client 認證方式(比如,簡單地直接將 Client 端密鑰發送給 AS)。

簡化模式

簡化模式不經過第三方應用程序的服務器,直接在瀏覽器中向認證服務器 申請令牌,跳過了“授權碼” 這個步驟,所以步驟都在瀏覽器中完成,令牌對訪問者是可見的,而且客戶端不需要認證。這種模式一般是用於客戶端應用程序,比如手機應用,桌面客戶端應用程序和運行於瀏覽器上的Web應用程序。授權令牌會交給用戶代理,再由用戶代理交給應用程序。如下圖:

技術分享

首先,還是用戶訪問客戶端,客戶端將用戶導向認證服務器。 https://www.example.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read

然後,用戶選擇是否給予客戶端授權:

技術分享

假如用戶給予授權,認證服務器將用戶導向客戶端事先指定的 “重定向URI” ,並且在 URI 的 hash 部分包含了訪問令牌: https://www.example.com/callback#token=ACCESS_TOKEN

then 瀏覽器向資源服務器發出請求,其中不包括上一步收到的 hash 值。

then 資源服務器返回一個網頁,其中包含的代碼可以獲取Hash 值中的令牌。

then 瀏覽器執行上一步獲得的腳本,提出令牌。

finally 瀏覽器將令牌發送給客戶端。

密碼模式

即用戶向客戶端提供用戶名密碼。客戶端使用這些信息,向 “服務商提供商” 索要授權。在這種模式下,客戶端不得存儲密碼。 這通常用在用戶對客戶端高度可信的情況下。 一般,認證服務器只有在其他授權模式無法執行的情況下,才能考慮使用這種模式。如下圖:

技術分享

  1. 用戶向客戶端提供用戶名,密碼。
  2. 客戶端用用戶名,密碼發送給認證服務器,向後者申請令牌。
  3. 認證服務器確認無誤後,向客戶端提供訪問令牌。

客戶端模式

客戶端使用自己的名義,而不是用戶的名義,向“服務提供商” 進行認證。嚴格來說,客戶端模式並不屬於OAuth 框架所需要解決的問題。在這種模式下,用戶直接向客戶端註冊,客戶端以自己的名義要求“服務提供商”提供服務,其實並不存在授權。如下圖:

技術分享

  1. 客戶端向認證服務器進行身份認證,並且要求一個訪問令牌。
  2. 認證服務器認證無誤後,向客戶端提供訪問令牌。

對於這種方式,用在 訪問一些和用戶無關的Open Api,比如一些首頁數據,這些數據和用戶無關,但是又不想任何人都可以調用這個WebApi,那麽就可以采用這種模式。

參考

  • 深入理解OAuth2.0協議

寫在最後

  1. 寫出來,說出來才知道對不對,知道不對才能改正,改正了才能成長。
  2. 在技術方面,希望大家眼裏都容不得沙子。如果有不對的地方或者需要改進的地方希望可以指出,萬分感謝。

OAuth認證