# OAuth 2.0 (The OAuth 2.0 Authorization Framework) 協議簡介 IETE 鎖定定義的公開標準[RFC6749](https://datatracker.ietf.org/doc/html/rfc6749) ## 如何獲取使用者授權 ## 如何向授權伺服器請求 Access Token ## 角色定義  |角色|說明| |-|-| |Resource Owner|資源擁有者,通常都是指「使用者」。| |Resource Server|資源伺服器,用來存放使用者受保護資源的伺服器。| |Client|應用程式,泛指對資源擁有者的資源有興趣的服務。| |Authorization Server|授權伺服器,專門用來處理授權的伺服器。|  ## OAuth 2.0 的 4 種授權類型 (Grant Type) * Authorization code grant 流程時序圖 * 這是常見也相較安全的授權類型。 *  * 這個流程有兩個關鍵: * 應用程式主要和使用者互動只有第 1 步,有另外兩個步驟是轉導行為,一個是第 2 步轉導去授權伺服器,另一個是第 5 步轉導回應用程式。這裡可以發現,應用程式是無法控制使用者授權行為,只能由使用者主動按「同意授權」,應用程式才能夠得到成功授權的結果。 * 使用者無法看到 Access Token 內容,因此攻擊者要偷取可用的 Token 是困難的。一般攻擊者可以透過植木馬或注入惡意程式碼到使用者電腦中,再讓瀏覽器執行程式把資料傳送給攻擊者。但使用者看不到 Access Token,攻擊的困難度就會提高。 因為 Authorization Code 授權流程設計上是完整且安全的,因此是目前 OAuth 2.0 主流的授權類型。 * Implicit grant 流程時序圖 * 正如其名,在授權流程中有部分的流程是被隱含完成的,主要是在取得 Token 的步驟時,省略了驗證應用程式身分的流程。這容易讓 Access Token 有被「非應用程式身分」的攻擊者偷走的風險。現已被 OAuth 2.0 Security BCP 文件 為不應該(SHOULD NOT)使用的流程,目前大多數的情境都有對應的解法,但只剩 SPA(Single-Page Application,協定裡的專有術語是稱為 Browser-Based Application)有可能還需要使用 Implicit 授權模式,其他基本上都應該採用 Authorization Code 授權模式。 *  * 問題主要在第 5 步:Access Token 放在 URI 的 Fragment 中。 * 雖然 HTTP 協定有提到請求資源的時候,不應該把 Fragment 包含在請求資源的一部分,但假設瀏覽器或伺服器沒有按照著這個協定實作的話,就有機會被中間人攻擊;另一方面,即便瀏覽器跟伺服器都有照著規範實作,因為 Fragment 依然是網址的一部分,Javascript 還是有辦法解析並取得 Access Token 的,若被 XSS 攻擊,Access Token 就有被偷的風險。 * 因為存在這些風險,因此 Implicit 被定為「不應該」使用的流程。 * Resource owner password credentials grant 流程時序圖 * 簡稱為 ROPC。這個授權類型與 Authorization Code 和 Implicit 一樣,會經由使用者授權,但不一樣的是:在這個流程裡,使用者不會經過授權伺服器,而是應用程式直接向使用者要求授權伺服器的驗證資訊來完成授權。 *  * 這個做法與最初提到的問題是類似的--應用程式會接收到使用者的帳號密碼,對使用者來說就會多一層風險。但使用帳密的方法是不同的,ROPC 是用帳密來交換 Access Token,後續存取資源就改用 Access Token,因此後續就不需要再儲存帳密,進而避免帳號密碼存明文的風險。 * 因為使用者的帳號密碼還是會需要經過應用程式,因此協定是建議這個授權類型僅用在應用程式是高度可信賴的時候,比方說應用程式是另一個子公司所開發的。 * 但是!事實上各種文章或是理論,都在說明 ROPC 授權類型存在非常多問題。 * Client credentials grant 流程時序圖 * 應用程式直接跟授權伺服器做驗證,不透過使用者授權。 *  * 主要應用在「應用程式本身就是資源擁有者」的情境,因此 Access Token 只能管理應用程式本身能管理的資源。像 GitHub 的 Personal Access Token 就是類似這樣的應用,只是它代表的是帳號的使用者本人,而不是應用程式。 ## 授權流程 - 以 Authorization Code Grant 為例 * 白名單: 確保`redirect_uri`可以正確導到正確的應用程式,避免黑客可以一直`try`其他的應用程式, * client 在開始授權之前,需要先跟授權伺服器註冊 client 的相關資訊 |註冊資訊|說明| |-|-| |client identifier|client 的唯一識別碼| |client authentication|client 驗證的方法,如[密碼](https://ithelp.ithome.com.tw/articles/10223365)或是[JWT](https://ithelp.ithome.com.tw/articles/10225934)等| |client password|client 的密碼驗證方法,若授權伺服器有發密碼的話,則必須提供[HTTP basic authentication scheme](https://ithelp.ithome.com.tw/articles/10223122)| 1. (步驟一) client 透過 User Agent 發出授權請求 (authrization request) 到授權伺服器的授權端口, * 請求帶有以下資訊: |欄位名稱|必要參數|說明| |-|-|-| |response_type|REQUIRED|指的是回應類型為何,此範例為<font color='red'>code</font>| |client_id|REQUIRED|client 預先註冊好的唯一識別碼| |redirect_uri|OPTIONAL|client 預先註冊好的轉導頁面| |scope|OPTIONAL|授權範圍| |state|RECOMMENDED|亂數,可用來確保授權請求與授權回應為同一使用者| * 參數使用<font color='red'>application/x-www-form-urlencoded</font>編碼後,把它作為 HTTP query 放到授權端口的後面,並產生 URI。接著讓 Client 使用 302 redirect 到此 URI。 * 補充 * 授權請求為`response_type: token`,回傳給 client 的時候 2. (步驟二) Client 拿到 code 之後,還不能當作通行證來做使用,需要再帶著`code`對授權伺服器提供的 token endpoint 發送 POST 請求。 3. (步驟三) 除此之外,還需要提供額外身分驗證資訊 - 指註冊所約定好的驗證方法。 |欄位名稱|必要參數|說明| |-|-|-| |grant_type|REQUIRED|協定規定為 authorization_code| |code|REQUIRED|授權成功回應的 code| |redirect_uri|REQUIRED|必須與授權請求 redirect_uri 相同| 4. (步驟四) 最後成功即可拿到 access token 資訊,以及 metadata |欄位名稱|必要參數|說明| |-|-|-| |access_token|REQUIRED|授權服務發行的 token| |token_type|REQUIRED|說明 access token 是何種型式| |expires_in|RECOMMENDED|Token 多久後會過期| |refresh_token|OPTIONAL|可用來重換新的 token| |scope|OPTIONAL最終接受的授權範圍| ## [Token Revocation、Token Introspection](https://ithelp.ithome.com.tw/articles/10226911) ### [OAuth 2.0 - 4.1.3. Access Token Request](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3) ### [OAuth 2.0 - 4.1.4. Access Token Response](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.4) ### [OAuth 2.0 - 5.2. Error Response](https://www.rfc-editor.org/rfc/rfc6749#section-5.2) ### 資料來源 [Miles](https://ithelp.ithome.com.tw/m/articles/10291817) [授權流程](https://ithelp.ithome.com.tw/articles/10226271) [Vue3 串接 Google OAuth 登入](https://ithelp.ithome.com.tw/articles/10304289) ### 延伸 #### [OpenID Connect](https://ithelp.ithome.com.tw/m/articles/10293020) * 與`Oauth2.0`差異比較 |OAuth 2.0 的角色|OpenID Connect 相似的角色|OpenID Connect 說明| |-|-|-| |Resource Owner|End-User|最終使用者(簡稱使用者),OpenID Connect 協定指的是真實的使用者。而在 OAuth 2.0 授權的情境裡,有可能應用程式同時也是資源擁有者,這點略為不同。| |Resource Server|UserInfo Endpoint|提供使用者資訊的端點,OpenID Connect 主要是處理身分驗證,因此這個端點是提供使用者相關的資訊為主。OAuth 2.0 就包山包海,不侷限在身分驗證的場景上。| |Client|Relying Party(RP)|直譯是依賴方,但稱之應用程式(Application)不會有誤解,也比較好討論。基本上與 OAuth 2.0 相同。| |Authorization Server|OpenID Provider(OP)|OpenID 服務提供者,提供 OpenID Connect 的服務,其實是指 Authorization Server 加上身分驗證功能的服務。| ##### 身分驗證請求與回應 * 身分驗證請求(Authentication Request) * 是基於授權請求再擴充出來的規格,`OpenID Connect`定義了獨立的授權範圍`openid` ,以及多個與身分驗證相關的自定義欄位。 * 身分驗證回應(Authentication Response) * 多了一個`ID Token`,內容是`JWT`,包含了使用者身分相關聲明(cliam),包括主體(subject)的唯一識別碼。 #### 定義並註冊回應模式 * 授權回應或是身分驗證回應,與`HTTP`回應(Response)是不同的。所以實務上,授權伺服器回應應用程式的方法,並不像`HTTP API`一樣有會有請求端點、方法或是回應狀態碼等。 * 此份協定定義了`Response Mode`作為回傳的方法,並使用新的參數`response_mode`指定。以下是定義的值,與實際的行為。 *  #### 定義多個回應類型的方法 *  #### 新增身分驗證相關的協定 * OpenID Connect 有額外定義一些身分驗證場景才會有的協定,如「從第三方啟動登入」這個協定就是授權場景沒有的;另外身分驗證相關的資訊其實是能夠定義得出來的,也就是 ID Token 的內容,如主體的唯一識別碼、身分驗證時間、Token 的發放與過期時間等;使用者的個人資訊也有額外定義聲明(Claims),如姓名、Email、生日等。 #### 新增身分驗證狀態管理 * 登入是使用者經過身分驗證完成,並保存已驗證狀態的一個過程,同時還會有另一個相對的行為是登出,是將已驗證狀態清除的過程。OpenID Connect 根據這個需求設計了狀態管理機制(Session Managerment)以及操作的方法。 * 另一個 Web 開發者所熟知的狀態管理機制--RFC 6265 - HTTP State Management Mechanism,也就是 Cookie 機制。Cookie 機制與 OpenID Connect 所定義的狀態管理不同的地方在於,Cookie 機制是依賴於網域,因此會有跨網域無法驗證的問題;而 OpenID Conect 要解決的問題就是跨網域的身分驗證和狀態管理,所以這也是兩種機制的主要差別。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up