簡介
OAuth 2 是一個授權框架,可以讓應用獲取一個 HTTP 服務(如 Facebook, GitHub, DigitalOcean)的用戶賬戶的有限的訪問。原理是通過持有用戶賬戶的服務主機驗證用戶身份后授權第三方應用訪問用戶賬戶。OAuth 2 為 web 和桌面應用、移動設備提供授權工作流程。
這篇信息指南針對應用程序開發人員,簡要說明了 OAuth 2 里的角色分類、授權類型、用例和工作流程。
從 OAuth 角色分類開始講起。
OAuth 角色分類
OAuth 定義了4種角色:
- 資源所有者
- 客戶端
- 資源服務器
- 授權服務器
接下來我們將詳細描述這幾個角色。
資源所有者:用戶
資源所有者是授權一個應用使用他們賬戶的用戶。應用使用用戶賬戶受限于授予的權限范圍(如:讀或寫權限)。
資源/授權服務器:API
資源服務器持有受保護的用戶賬戶,由它來驗證用戶身份然后將訪問口令傳給應用。
以應用開發者的角度來看,一個服務的 API 既是資源服務器也是授權服務器。我們將這兩個角色結合成服務方角色或 API 角色。
客戶端:應用
客戶端就是想要使用用戶賬戶的應用。在這之前,需要經過用戶授權,而授權的驗證由 API 來做。
抽象協議工作流程
現在你對 OAuth 角色分類有了一些了解,接著通過一個圖來看他們是如何協作的:
該圖詳細解釋:
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 授權碼。
下面是授權碼類型工作流程圖:
步驟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:用戶授權給應用
當用戶點擊上面那個鏈接,如果沒有登錄的話首先應該登錄到那個服務。然后服務方提示用戶是否要授權給那個應用使用他們的賬號。下圖是一個授權提示:
上圖是 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(在服務方那邊注冊了的)就可以提供這個服務了。
隱式授權類型不支持更新口令。
隱式授權類型基本工作流程如下:應用要求用戶授權,然后授權服務器傳回訪問口令給用戶代理,用戶代理將其傳遞給應用。下圖是詳細點的過程圖:
步驟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