# 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
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.