【譯文】OAuth 2 介紹

weixin_34234823發表於2017-08-31

原文:An Introduction to OAuth 2

簡介

OAuth 2 是一個授權框架,可以讓應用獲取一個 HTTP 服務(如 Facebook, GitHub, DigitalOcean)的使用者賬戶的有限的訪問。原理是通過持有使用者賬戶的服務主機驗證使用者身份後授權第三方應用訪問使用者賬戶。OAuth 2 為 web 和桌面應用、移動裝置提供授權工作流程。

這篇資訊指南針對應用程式開發人員,簡要說明了 OAuth 2 裡的角色分類、授權型別、用例和工作流程。

從 OAuth 角色分類開始講起。

OAuth 角色分類

OAuth 定義了4種角色:

  • 資源所有者
  • 客戶端
  • 資源伺服器
  • 授權伺服器

接下來我們將詳細描述這幾個角色。

資源所有者:使用者

資源所有者是授權一個應用使用他們賬戶的使用者。應用使用使用者賬戶受限於授予的許可權範圍(如:讀或寫許可權)。

資源/授權伺服器:API

資源伺服器持有受保護的使用者賬戶,由它來驗證使用者身份然後將訪問口令傳給應用。

以應用開發者的角度來看,一個服務的 API 既是資源伺服器也是授權伺服器。我們將這兩個角色結合成服務方角色或 API 角色。

客戶端:應用

客戶端就是想要使用使用者賬戶的應用。在這之前,需要經過使用者授權,而授權的驗證由 API 來做。

抽象協議工作流程

現在你對 OAuth 角色分類有了一些瞭解,接著通過一個圖來看他們是如何協作的:


2463185-a663f68f6d8bc8a3.png
抽象協議工作流程圖

該圖詳細解釋:
1、應用請求使用者授權訪問服務方資源。
2、如果使用者授權了,應用收到授權許可。
3、應用提供可以證實自己的身份證明和授權許可向授權伺服器(API)請求訪問口令(access token)。
4、如果應用的身份證明和授權許可都通過了驗證,授權伺服器(API)傳送一個訪問口令給應用,授權完成。
5、應用提供訪問口令從資源伺服器(API)請求資源。
6、如果訪問口令有效,資源伺服器(API)提供資源給應用。

實際流程因授權型別不同會有不同,這是總體的思路。之後我們將探索不同的授權型別。

應用註冊

在應用使用 OAuth 之前你必須在這個服務上註冊你的應用。這需要通過在服務網站上填寫一個『開發者』或『API』登錄檔單,表單需要提供以下資訊(可能還有應用詳細資訊):

  • 應用名字
  • 應用網站
  • 重定向 URI 或回撥 URL

重定向 URI 是在使用者授權(或拒絕授權)以後服務方要重定向的位置,也就是你的應用處理授權碼或訪問口令的地方。

客戶端 ID 和客戶端金鑰

在你的應用註冊後服務方會給你一個以客戶端標誌符(ID)和客戶端金鑰為代表的『客戶端證書』。客戶端 ID 是一個公開暴露的字串,用於服務 API 標識這個應用,也用於生成授權相關的各種 URL。客戶端金鑰用於在應用請求訪問使用者賬戶時服務 API 鑑定應用身份,必須要保證在應用和 API 之間私有。

授權許可

在之前的抽象協議工作流程裡,前四步獲得授權許可和訪問口令。授權許可型別依賴於應用請求授權所使用的方法和 API 支援的許可型別。OAuth 2 規定了4種批准型別,在不同的案例裡使用不同的批准型別:

  • 授權碼:用於伺服器端應用。
  • 隱含:用於手機應用或網頁應用(即執行於使用者裝置的應用)
  • 資源所有者密碼驗證:用於受信賴的應用,如服務方自己持有的應用。
  • 客戶端驗證:用於應用 API 訪問。

接著我們要詳細說下不同型別的用例和工作流程。

授權型別:授權碼

授權碼型別是最常用的型別,充分利用了伺服器端應用程式碼不公開的優點,即客戶端金鑰可以保持私有。該模式是一種基於重定向的流程,這意味著應用必須可以和使用者代理(如使用者的瀏覽器)進行互動且要能收到使用者代理轉發的 API 授權碼。

下面是授權碼型別工作流程圖:

2463185-02ae4d454a4b9c4f.png
授權碼模式流程圖

步驟1:授權碼連結

首先使用者得到一個像這樣的授權碼連結:

https://cloud.digitalocean.com/v1/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read

連結組成部分:

  • https://cloud.digitalocean.com/v1/oauth/authorize:授權 API 端點
  • response_type=code:表明應用正在請求授權碼
  • client_id=CLIENT_ID:應用的客戶端 ID(用於 API 辨認應用身份)
  • redirect_uri=CALLBACK_URL:服務方在授予授權碼後將使用者代理重定向的位置
  • scope=read:表明應用請求的許可權範圍

步驟2:使用者授權給應用

當使用者點選上面那個連結,如果沒有登入的話首先應該登入到那個服務。然後服務方提示使用者是否要授權給那個應用使用他們的賬號。下圖是一個授權提示:

2463185-7307ae2eba73bc3d.png
授權提示圖

上圖是 DigitalOcean 的授權頁面截圖,可以看到『Thedropletbook』應用正在請求『manicas@digitalocean.com』賬號的『讀』許可權。

步驟3:應用收到授權碼

如果使用者點選『授權給應用』,服務方將使用者代理重定向到應用之前提供的重定向 URI,這時 URI 帶有授權碼。重定向的網址看起來像這樣(假設應用網址是"dropletbook.com"):

https://dropletbook.com/callback?code=AUTHORIZATION_CODE

步驟4:應用請求訪問口令

應用使用授權碼和客戶端金鑰向 API 請求訪問口令。下面是一個 POST 請求口令的例子:

https://cloud.digitalocean.com/v1/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL

步驟5:應用收到訪問口令

如果驗證通過,API 將返回一個包含訪問口令的響應(和一個可選的更新口令)。完整的響應看起來像這樣:

{
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":2592000,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"read",
  "uid":100101,
  "info":{
    "name":"Mark E. Mark",
    "email":"mark@thefunkybunch.com"
  }
}

現在應用已經獲得了授權!接下來可能使用訪問口令來訪問使用者的賬號,當然訪問受所授的許可權限制,直到口令到期或被取消授權。如果有收到更新口令(refresh token),可以在當前口令過期後用它來請求新的口令。

授權型別:隱式

隱式授權型別用於手機應用或 web 應用(也就是執行在 web 瀏覽器的應用),這類應用的客戶端金鑰私密性沒有保障。隱式授權型別同樣是基於重定向的工作流程,只是訪問口令是給使用者代理也就是應用的,所以訪問口令可能暴露給使用者和使用者裝置上的其它應用。同時,這個流程不需要驗證應用身份,只要有重定向的 URI(在服務方那邊註冊了的)就可以提供這個服務了。

隱式授權型別不支援更新口令。

隱式授權型別基本工作流程如下:應用要求使用者授權,然後授權伺服器傳回訪問口令給使用者代理,使用者代理將其傳遞給應用。下圖是詳細點的過程圖:

2463185-a9eb0e8f75bdbdac.png
隱式授權流程圖

步驟1:隱式授權連結

在隱式授權型別裡,一個向 API 請求口令的授權連結代表了使用者。這個連結就像是授權碼連結,只是它是請求一個口令而不是授權碼(注意響應型別是口令):

https://cloud.digitalocean.com/v1/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read

步驟2:使用者授權給應用

當使用者點選上面那個連結,需要先登入到服務方來驗證使用者的身份。然後使用者將看到服務方提示是否授權給應用。提示就像之前說過的那樣。

步驟3:使用者代理重定向到帶有訪問口令的指定網址

如果使用者點選了『授權』,服務方將使用者代理重定向到應用提供的重定向地址,重定向時包含訪問口令。它看起來像這樣:

https://dropletbook.com/callback#token=ACCESS_TOKEN

步驟4:使用者代理遵循重定向 URI

使用者代理保持帶有訪問口令的 URI。

步驟5:應用傳送提取訪問口令指令碼

應用返回一個帶有可以從整個重定向 URI 裡提取口令的指令碼的網頁。

步驟6:訪問口令傳給應用

使用者代理執行給出的指令碼然後把訪問口令傳遞給應用。

現在應用已經獲得了授權!接下來可能使用訪問口令來訪問使用者的賬號,當然訪問受所授的許可權限制,直到口令到期或被取消授權。

授權型別:資源持有者密碼驗證

在這個型別裡,使用者直接提供他們在服務方那邊的憑證(使用者名稱和密碼)給應用,用這些憑證可以從服務方那邊獲得訪問口令。這種授權型別只有在別的授權型別不可行的時候用於授權伺服器上。或者只有在應用可信的情況下使用(如服務方持有的應用或使用者作業系統應用)。

密碼驗證流程

在使用者提供憑證給應用後應用將向授權伺服器請求訪問口令。POST 請求看起來像這樣:

https://oauth.example.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID

如果使用者憑證通過驗證,授權伺服器返回訪問口令給應用。現在應用已被授權!

注意:DigitalOcean 目前不支援這種授權,所以上面的連結指向虛構的授權伺服器『oauth.example.com』。

授權型別:客戶端驗證

這種授權型別給應用提供了一種讓應用自己管理服務賬號的方式。使用場景是應用想要更新其註冊的描述或重定向的 URI,又或者通過 API 訪問其它儲存於服務賬號上的資料。

客戶端驗證流程

應用通過傳送憑證(應用的客戶端 ID 和客戶端金鑰)給授權伺服器請求訪問口令。POST 請求看起來像這樣:

https://oauth.example.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET

如果憑證通過了驗證,授權伺服器返回訪問口令給應用。

訪問口令使用用例

應用有了訪問口令以後可能通過 API 訪問可訪問的使用者賬戶資訊。

一下是一個使用 curl 的 API 請求例子(注意這裡包含了訪問口令):

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN""https://api.digitalocean.com/v2/$OBJECT"

假設訪問口令有效,將以 API 文件裡寫的那樣執行這個 API。如果訪問口令沒有通過驗證,將返回一個『invalid_request』錯誤。

更新口令流程

在一個訪問口令過期後,再使用它來訪問 API 將收到『Incalid Token Error』。在這一點上,如果一開始獲取訪問口令的時候同時也返回了更新口令,更新口令可以用於請求一個新的訪問口令。

以下是一個使用了更新口令的 POST 請求新訪問口令例子:

https://cloud.digitalocean.com/v1/oauth/token?grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN

結論

現在你應該對 OAuth 2 如何工作有了很好的瞭解,知道何時改使用何種授權流程。

如果想學習更多關於 OAuth 2 的知識,可以看看下面這幾篇文:
How To Use OAuth Authentication with DigitalOcean as a User or Developer
How To Use the DigitalOcean API v2
The OAuth 2.0 Authorization Framwork

相關文章