1. 程式人生 > >要用Identity Server 4 -- OAuth 2.0 超級簡介

要用Identity Server 4 -- OAuth 2.0 超級簡介

分隔 理解 大小 很多 應用程序 identity 復制 字符串 返回

OAuth 2.0 簡介

OAuth有一些定義:

OAuth 2.0是一個委托協議, 它可以讓那些控制資源的人允許某個應用以代表他們來訪問他們控制的資源, 註意是代表這些人, 而不是假冒或模仿這些人. 這個應用從資源的所有者那裏獲得到授權(Authorization)access token, 隨後就可以使用這個access token來訪問資源.

(這裏提到的假冒或模仿就是指在客戶端復制一份用戶名和密碼,從而獲取相應的權限)。

OAuth 2.0是一個開放的協議, 它允許使用簡單和標準的方法從Web, 移動或桌面應用來進行安全的授權(Authorization).

從這些定義可以看出來, OAuth2 是關於授權(Authorization)的, 客戶端應用可以請求access token, 使用這個token就可以訪問API資源了.

因為有很多種類客戶端應用的存在, 例如ASP.NET Core MVC, Angular, WPF 等等, 它們都是不同的應用類型, 所以, OAuth2 定義了不同類型的客戶端應用應該如何安全的完成授權. OAuth2標準還定義了一些端點, 並且定義了針對不同類型的客戶端應用如何使用這些端點.

Identity Server 4 和 Azure AD 都實現了OAuth 2.0 標準.

但是上面提到的access token只能用來訪問資源, 它無法被用來登錄客戶端應用. 登錄這種操作叫做認證/身份驗證(Authentication), 而OpenID Connect則可以完成這項工作.

OpenID Connect 簡介

OpenID Connect是建立在OAuth2協議上的一個簡單的身份標識層, 所以OpenID Connect兼容OAuth2.

使用OpenID Connect, 客戶端應用可以請求一個叫identity token的token, 它會和access token一同返回給客戶端應用. 這個identity token就可以被用來登錄客戶端應用程序, 而這個客戶端應用還可以使用access token來訪問API資源.

OpenID Connect還定義了一個UserInfo端點, (OAuth2定義了Authorization端點和Token端點

)它允許客戶端應用獲取用戶的額外信息.

此外它還定義了不同類型的應用如何從身份識別提供商(IDP)安全的獲取這些token.

綜上, OpenID Connect是更高級的協議, 它擴展並替代了OAuth2. 盡管現在我們經常說我們在使用OAuth2來保護API, 其實更準確的說, 大多數情況下, 我們使用的是OpenID Connect.

如果到現在還是不明白OAuth2和OpenID Connect也沒關系, 這不是幾句話就能描述清楚的東西. 本文我進一步介紹OAuth 2.0.

OAuth 2.0 進一步介紹

OAuth2的目標就是讓客戶端應用可以代表資源所有者(通常是用戶)來訪問被保護的資源:

技術分享圖片

  • 這裏的資源所有者(Resource Owner), 他擁有訪問API資源的權限, 並且他還可以委派權限(delegate)給其他應用來訪問API. 資源所有者通常是可以使用瀏覽器的人.
  • 被保護的資源(Protected Resource)就是資源所有者擁有權限去訪問的組件, 它可以是很多種形式的, 但是web API的形式還是最常見的.
  • 客戶端(Client)應用就是代表資源所有者訪問被保護資源的一個軟件. 註意它既不是指瀏覽器, 也不是指給你錢讓你開發軟件的人. 在OAuth2裏面, 它是指被保護的API資源的消費者.

委拖/委派權限

前面提到OAuth2裏面, 最終用戶可以委派他的一部分權限給客戶端應用來代表最終用戶來訪問被保護的資源. 但是要完成這件事, 還需要一個橋梁來連接客戶端應用和被保護資源. 這個組件叫做授權服務器(Authorization Server, AS). 這個授權服務器也許就是資源服務器, 但是大多數情況下它們是不同的服務器.

授權服務器(AS)是被受保護的資源所信任的, 它可以發行具有特定目的的安全憑據給客戶端應用, 這個憑據叫做OAuth的 access token.

想要獲得access token, 客戶端應用首先要把資源所有者發送給授權服務器

技術分享圖片

首先客戶端需要獲得權限, 它可能有兩種方式來獲得權限: 可以從資源所有者那裏直接獲得權限, 也可以讓授權服務器作為中介, 從授權服務器那裏間接的獲得權限. (上面這個圖中描述的是從資源授權者直接獲得權限的流程).

如果使用授權服務器作為中介的話, 客戶端需要把資源所有者發送到授權服務器(可以理解為最終用戶使用的瀏覽器被重定向到了授權服務器), 然後資源所有者在這可以對客戶端應用進行授權.

這時資源所有者要通過身份認證進入授權服務器, 通常還會有一個是否同意授權客戶端應用請求的選項, 點擊同意後就授權了. 而從客戶端應用的角度講呢, 它可以向資源所有者請求他一部分的功能和範圍(scope), 在將來, 資源所有者可能會逐漸減少它所擁有的功能和範圍.

到這裏, 上面寫的這個動作/東西叫做授權(authorization grant).

一旦執行了授權動作也就是客戶端得到了授權(這個授權是一個可以代表資源所有者權限的憑據), 客戶端便可以從授權服務器請求access token了. 這個access token就可以被用來訪問被保護的資源了.

下圖是使用授權服務器作為中介的流程圖, 除了授權, 其它部分和上圖表達的都是一個意思:

技術分享圖片

授權 Authorization Grant

授權 (authorization grant) 是一個代表著資源所有者權限的憑據, 它可以被客戶端應用來獲取access token. OAuth2裏面定義了4種類型的授權, 分別是: auhtorization code, implicit, resource owner password credentials, client credentials. OAuth2還定義了一個擴展機制以便定義其它的授權類型.

用一句話描述就是, 授權(Authorization Grant)就是獲取token的方法.

1. Authorization Code

Authorization Code是使用授權服務器作為客戶端和資源所有者的中介來獲取的. 所以這裏不是采用直接從資源所有者獲得授權的方式, 而是采用授權服務器作為中介的方式. 在授權服務器把資源所有者送回到(重定向)客戶端的時候帶著這個臨時的憑據: authorization code (我暫時叫它授權碼吧), 它就代表著資源所有者委托給客戶端應用的權限.

Authorization code在安全方面有一些重要的優點: 可以對客戶端應用進行身份認證; access token是直接發送到客戶端應用的, 不經過資源所有者的瀏覽器, 所以不會暴露access token給外界, 包括資源所有者.

2. Implicit

Implicit, 我叫它隱式授權吧. 它是Authorization Code的一個簡化版本, 它針對瀏覽器內的客戶端應用(例如js, angular的應用)進行了優化. 在implicit流程裏, 沒有給客戶端發送授權碼(authorization code), 而是直接給它發送了access token. 之所以叫這種授權類型implicit, 是因為流程裏並沒有發行任何中間憑據.

在implicit流程裏發行access token的時候, 授權服務器並沒有對客戶端應用進行身份認證. 某些情況下, 客戶端的身份可以通過帶著access token重定向回客戶端的URI來驗證. acces token可能會暴露給任何使用該瀏覽器的人或者應用.

Implicit授權確實可以提高瀏覽器內應用的響應性和效率, 畢竟它減少了來回往返的次數. 但是方便可能會帶來風險, 建議如果可以的話盡量使用Authorization Code, 當然這個需要自己去權衡.

3. Resource Owner Password Credentials

Resource Owner Password Credentials, 資源所有者密碼憑據. 顧名思義, 可以直接使用密碼憑據(用戶名和密碼)作為授權來獲得access token. 只有當資源所有者和客戶端之間高度信任的時候並且其它授權方式不可用的時候才可以使用這種授權方式.

這裏資源所有者的憑據只應該用於一次請求並用於交換access token. 這種授權方式可以讓客戶端免於存儲資源所有者的憑據(如果以後還需要使用的話), 通過交換一個長期有效的access token或refresh token都可以達到這種效果.

4. Client Credentials

Client Credentials. 有時候, 資源或者叫資源服務器並不屬於某個最終用戶, 也就是沒有資源所有者對該資源負責. 但是客戶端應用肯定還是要訪問這些資源, 這時候就只能使用Client Credentials這種授權方式了.

OAuth 2.0 的角色和組件

OAuth2的4個角色前面已經介紹過, 分別是: 資源所有者 Resource Owner, 客戶端 Client, 被保護資源 Protected Resource, 和 授權服務器 Authorization Server.

而OAuth2的組件, 前面也都有提到過, 它們是: Access Token, Refresh TokenScope (範圍).

下面簡單介紹下這幾個組件.

Access Token: 有時候只被叫做token, 它是用來訪問被保護資源的憑據. 它是一個字符串, 它代表了給客戶頒發的授權, 也就是委托給客戶的權限. OAuth2本身並沒有對access token的格式或內容進行定義. 但是access token裏面要描述出資源所有者授予的訪問權限的範圍和持續時間.

Access Token 通常對客戶端應用是不透明的, 也就是說客戶端無需去查看access token. 客戶端的任務就是把它展示給被保護的資源. 其實access token在整個OAuth2系統裏對任何角色都是不透明的, 授權服務器的任務只是發行token, 而被保護資源的任務是驗證token. 但是它們都必須理解access token的構成, 並知道access token代表了什麽. 而客戶端對於access token應該是完全健忘的.

Scopes: OAuth2的scope表示被保護資源那裏的一套權限. 在OAuth2裏面, scope用區分大小寫的字符串表示, 可以用空格作為分隔符來表示多個scope. 這些字符串由授權服務器來定義. 而scope字符串的格式和結構在OAuth2裏並沒有定義.

Scope對於限制客戶端應用的訪問權限有很重要的作用. 客戶端應用可以請求一些scopes, 而授權服務器可以允許資源所有者授權或者拒絕特定的scopes. Scope還具有疊加性.

Refresh Token: Refresh Token是用來獲得Access Token的憑據. 和acces token差不多, refresh token也是由授權服務器發行給客戶端應用的, 客戶端不知道也不關心refresh token裏面有啥. 但與access token不同的是, refresh token不會被發送給被保護的資源. 客戶端是用refresh token來請求新的access token (尤其是當現在的access token過期或者失效時), 但這個過程就不需要資源所有者的參與了. Refresh Token是可選的, 授權服務器會酌情發行refresh token, 如果需要的話, refresh token是在發行access token一同返回的.

此外refresh token還具備讓客戶端應用逐漸降低訪問權限的能力.

通過refresh token來取得新的access token的流程如下:

技術分享圖片

另外一張彩色圖:

技術分享圖片

這張彩圖的中文意思是: 客戶端使用當前access token訪問被保護資源的時候, access token失效或者過期了, 這是從被保護資源返回了一個錯誤響應; 然後客戶端使用refresh token向授權服務器請求了一個新的access token; 得到新的access token後, 客戶端使用新的access token請求被保護資源, 這時資源就可以被正常的返回給客戶端了.

OAuth 2.0的端點

OAuth2定義了一套端點(Endpoint), 端點就是web服務器的一個訪問路徑URI.

OAuth2定義的端點有授權端點, Token端點, 它們都在授權服務器上.

OAuth2沒有定義這些端點URI應該如何被發現和文檔的結構.

授權端點(authorization endpoint)是用來和資源所有者交互的, 資源所有者在這裏進行登錄(身份認證), 然後通過該端點可以對客戶端進行授權(authorization grant). 授權服務器首先要驗證資源所有者的身份, 但是驗證的方式並不在OAuth2的協議範圍內.

Token端點(token endpoint), 客戶端通過向token端點展示它的授權(auhtorization grant)或refresh token來獲取access token. 除了implicit之外所有的授權類型都需要使用該端點, 因為implicit的access token是直接發行的.

本篇文章先到這. 下篇文章再簡單介紹一下OpenId Connect.

那四種授權類型具體的詳細流程將在介紹Identity Server 4的時候一同介紹.

要用Identity Server 4 -- OAuth 2.0 超級簡介