一個故事,搞懂 OAuth 2.0 與 OIDC

Posted by MingLun Allen Wu on Friday, September 26, 2025

前言:為什麼研究 OAuth 2.0 和 OIDC ?

前陣子在工作中接觸到 Workload Identity Federation (WIF),發現背後繞不開 OAuth 2.0OIDC

雖然這些名詞之前也看過,但總是混淆,對於細節的掌握度也不高。

於是我花了一些時間研究,並透過一個小故事來整理筆記。


皇帝、大將軍與玉璽

直接交玉璽的風險

想像你是某個王朝的皇帝。某天邊關告急,外族入侵,朝堂上聲望極高的大將軍請纓出兵平亂。

要讓大將軍能調兵,最快的方法是把「傳國玉璽」交給大將軍。玉璽象徵皇權,見玉璽如見皇帝,各地軍營自然會聽命。

但問題也很明顯:

如果大將軍心懷不軌,拿著玉璽就能隨意調動兵馬,甚至反過來攻打皇宮。

這樣的權力過於集中,風險太大。

1


多一道程序 : 詔書、腰牌與虎符

為了降低風險,皇帝(你)設計了一個新流程 :

  1. 大將軍先上奏,說明需要多少兵馬、出兵目的。
  2. 奏摺經御前總管轉呈,皇帝審核後頒布「詔書」。

2

如果僅憑詔書即可調兵,很有可能在傳遞的過程中,詔書被調包,讓有心之士偽冒大將軍的身份。

3

爲了避免此問題,在將軍取得詔書後,必須憑藉詔書和自己獨有的腰牌來「驗明身份」,才能兌換「虎符」。

4

這樣一來,就算詔書在傳遞過程被調包,沒有大將軍的腰牌,也無法換到虎符。

5

而虎符是唯一能調動兵馬的信物,權限被限制在皇帝核可的範圍內。

6


把故事翻譯成技術語言

讓我們試著把故事裡的角色翻譯成技術語言 :

故事角色意涵現實定義或範例OAuth 2.0 / OIDC 名詞
皇帝擁有最高權力的人使用者本人,真正擁有資料的人
(例:Google 帳號的擁有者)
Resource Owner
部隊完成任務所需的資源使用者的資料
(例 : Google Calendar 的事件)
Resource
大將軍代替皇帝執行任務想存取資料的應用程式
(例:行程管理 App)
Client
御前總管皇帝與將軍之間的中介負責驗證身份、簽發授權碼和 Token 的伺服器Authorization Server
傳國玉璽皇權象徵使用者的帳號密碼
(最直覺但高風險)
Password
兵營管理部隊的地方儲存並保護資料的伺服器
(例 : Google Calendar API)
Resource Server
詔書皇帝的臨時命令Authorization Server 簽發的一次性授權碼Authorization Code
腰牌將軍自身的憑證Client 用來證明自己身份的密鑰Client Secret
虎符最終能調兵的信物能直接存取資源的憑證Access Token

OAuth 2.0 流程解析

理解故事後,讓我們再用技術語言把流程走一次。

假設我們 (Resource Owner) 今天使用一個管理行程的 App (Client) ,這個 App 能夠存取使用者的 Google Calendar (Resource Server) 來匯入行程資訊 (Resource)。

如果你直接將 Google 的密碼交給 Client,很難確保它只做約定好的行為 (例如:「讀取」行程) 。

OAuth 2.0 希望能解決的問題就是:

如何讓 Application 可以取得我的資料? (但不要擁有我的密碼)

Step 1 - 使用者授權

  • 使用者 (Resource Owner) 想讓 App (Client) 存取 Google Calendar (Resource Server)。
  • App (Client) 導向 Google 的 Authorization Server 並送出幾個資訊 :
    • redirect_uri : 認證完成後,要將結果回傳至何處。
    • scope : Client 需要的權限及資源。
    • 除了這兩個資訊外,還有 client_idstate,因篇幅關係暫不討論。

7

Authorization Server 會根據 Client 提交的 Scope,轉換成容易閱讀的授權畫面,稱為 Consent :

8

Step 2 - Authorization Code

  • 使用者 (Resource Owner) 核准後,Authorization ServerAuthorization Code 回傳至 Client 的 redirect_uri。
  • Authorization Code 本身不能直接存取資料。(如同故事裡的詔書必須換成虎符)

9

Step 3 - 換取 Token (Back Channel)

Client 收到 Authorization Code 後,會再向 Authorization Server 換取關鍵的 Access Token

為什麼要進行第二步交換呢?細節在於:交換的方式不同

Step 1 ~ 2 屬於 “Front Channel” : 資訊會經過瀏覽器,容易被攔截。

而換取 Access Token 時,是由 Client 的後端直接和 Authorization Server 溝通,為了確認請求是由合法的 Client 發出,Client 需要同時附上事先與 Authorization Server 約定好的 Client Secret

Authorization Server 驗證正確後,才會簽發 Access Token,後續才能用來取用資源。

10

Step 4 - 使用 Access Token

  • Client 帶著 Authorization: Bearer <access_token> 呼叫 Resource Server (例如:Google Calendar API)。
  • Resource Server 驗證 Access Token 後,回傳資料。

至此,Client 成功在沒有使用者密碼的情況下,取用資料。

11


OAuth 2.0 的不足

雖然 OAuth 2.0 解決了 “Authorization” 的問題,但它並沒有辦法處理 “Authentication”。

原因在於 OAuth 2.0 的設計初衷,是讓第三方應用程式能在使用者同意的前提下,取得有限範圍的存取權限,而不是確認「這個人是誰」。

在流程中,Client 拿到的 Access Token,只能代表:

使用者 (Resource Owner) 授權了某些操作(例如讀取日曆)。

Access Token 並沒有描述使用者的身份。

Client 可以使用它去存取 API,但無法判斷「持有這個 Token 的人是 Allen, Bob 還是 MingLun」。

如果有人單純把 OAuth 2.0 當成「登入機制」,其實是誤用。因為單靠 OAuth 2.0,應用程式 (Client) 只能知道「有一個人給了我授權」卻不知道「這個人是誰」。

為了解決這個缺口,才會誕生後來的 OpenID Connect (OIDC),在 OAuth 2.0 的基礎上補上「身份驗證」(Authentication) 的能力。


OIDC : 補上身份驗證

OIDC 協定其實就是在 OAuth 2.0 的基礎上,加入額外 5 ~ 10 % 的 Layer 擴充,卻帶來關鍵性的差別:

12

具體來說,OIDCOAuth 2.0 基礎上加入了:

  1. ID Token :
    • Authorization Server 簽發的 JWT,內含使用者的識別資訊。
    • 這讓 Client 能在獲得授權的同時,也知道「使用者是誰」。
  2. UserInfo Endpoint :
    • 支援 OIDC 協定的 Authorization Server 都會實作這個 API Endpoint,Client 可以使用 Access Token 呼叫,進一步取得使用者的詳細資訊。

流程與 OAuth 2.0 相同,只是在 Scope 中可以加入 openid

13

ClientScope 包含 openid 時,Authorization Server 除了 Access Token 還會額外回傳 ID Token

14

ID Token 以 JWT 的形式存在,經過適當的驗證和解碼後,就能確認使用者身份。

這組 JWT 包含三個部分 :

  • Header
  • Payload (Claims)
  • Signature

其中 Payload 的部分經過反解後,會包含類似下列資訊 :

{
  "iss": "https://accounts.google.com",     // 發行者 (Issuer)
  "sub": "110169484474386276334",           // 使用者唯一 ID,不會隨 email 更改
  "aud": "s6BhdRkqt3",                      // 此 Token 的受眾 (Audience),通常是 Client ID
  "exp": 1311281970,                        // Token 到期時間 (Unix Timestamp)
  "iat": 1311280970,                        // Token 簽發時間
  "auth_time": 1311280969,                  // 使用者通過驗證的時間
  "email": "minglunwu@gmail.com",           // 使用者 Email (可變動資訊)
  "email_verified": true,                   // Email 是否已驗證
  "name": "MingLun Wu"                      // 使用者名稱
}

關於 JWT 的部分,礙於篇幅關係,不多做介紹。重點在於:

ID Token 經過 Decode 後,可以從 Payload 中取得基本的使用者資訊。

Client 取得使用者資訊後,即可進行驗證,完成 “Authentication”。

如果需要更多資訊,則可以呼叫 UserInfo 的 endpoint 來取得更多用戶資料。


小結:授權與驗證的邊界

整理到這裡,可以看到兩者的差異:

  • OAuth 2.0 的核心是授權 (Authorization):讓應用程式在不拿到密碼的情況下,能安全地存取資料。
  • OIDC 則在此基礎上補上身份驗證 (Authentication):讓應用程式知道「這個人是誰」。

換句話說:OAuth 2.0 解決「能不能取資料」,OIDC 解決的是「誰在取資料」。

理解這層分工後,再回頭看 Workload Identity Federation (WIF),會發現它的本質也是相同的: 只是把「使用者登入」換成「Workload 之間的信任交換」,背後仍是 OAuth 2.0 / OIDC 的精神在運作。

關於 WIF 的內容,留待下篇筆記。


Reference & Credit

如果你想更深入理解 OAuth 2.0OIDC,我強烈推薦這支影片:

影片長約一小時,但講解得非常完整、清楚。

這篇筆記的靈感和部分理解也受到它的啟發。


結語

希望今天這篇分享能幫助你更快了解 OAuth 2.0OIDC 的核心概念。

謝謝你的閱讀,我們下次見。


About Byte & Ink

我會定期在部落格分享不同主題的文章,目前包含:

如果你覺得內容有幫助,歡迎你點此訂閱我的文章,你的訂閱會帶給我更多動力,持續分享有意義的內容!



See Also