前言:為什麼研究 OAuth 2.0 和 OIDC ?
前陣子在工作中接觸到 Workload Identity Federation (WIF),發現背後繞不開 OAuth 2.0 和 OIDC。
雖然這些名詞之前也看過,但總是混淆,對於細節的掌握度也不高。
於是我花了一些時間研究,並透過一個小故事來整理筆記。
皇帝、大將軍與玉璽
直接交玉璽的風險
想像你是某個王朝的皇帝。某天邊關告急,外族入侵,朝堂上聲望極高的大將軍請纓出兵平亂。
要讓大將軍能調兵,最快的方法是把「傳國玉璽」交給大將軍。玉璽象徵皇權,見玉璽如見皇帝,各地軍營自然會聽命。
但問題也很明顯:
如果大將軍心懷不軌,拿著玉璽就能隨意調動兵馬,甚至反過來攻打皇宮。
這樣的權力過於集中,風險太大。

多一道程序 : 詔書、腰牌與虎符
為了降低風險,皇帝(你)設計了一個新流程 :
- 大將軍先上奏,說明需要多少兵馬、出兵目的。
- 奏摺經御前總管轉呈,皇帝審核後頒布「詔書」。

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

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

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

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

把故事翻譯成技術語言
讓我們試著把故事裡的角色翻譯成技術語言 :
| 故事角色 | 意涵 | 現實定義或範例 | 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_id和state,因篇幅關係暫不討論。

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

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

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,後續才能用來取用資源。

Step 4 - 使用 Access Token
Client帶著Authorization: Bearer <access_token>呼叫Resource Server(例如:Google Calendar API)。Resource Server驗證Access Token後,回傳資料。
至此,Client 成功在沒有使用者密碼的情況下,取用資料。

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 擴充,卻帶來關鍵性的差別:

具體來說,OIDC 在 OAuth 2.0 基礎上加入了:
- ID Token :
- 由
Authorization Server簽發的 JWT,內含使用者的識別資訊。 - 這讓
Client能在獲得授權的同時,也知道「使用者是誰」。
- 由
- UserInfo Endpoint :
- 支援
OIDC協定的Authorization Server都會實作這個 API Endpoint,Client可以使用Access Token呼叫,進一步取得使用者的詳細資訊。
- 支援
流程與 OAuth 2.0 相同,只是在 Scope 中可以加入 openid。

當 Client 的 Scope 包含 openid 時,Authorization Server 除了 Access Token 還會額外回傳 ID Token。

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.0 與 OIDC,我強烈推薦這支影片:
影片長約一小時,但講解得非常完整、清楚。
這篇筆記的靈感和部分理解也受到它的啟發。
結語
希望今天這篇分享能幫助你更快了解 OAuth 2.0 及 OIDC 的核心概念。
謝謝你的閱讀,我們下次見。
About Byte & Ink
我會定期在部落格分享不同主題的文章,目前包含:
- 職涯心得
- 個人成長
- 筆記軟體 - Obsidian 教學
- 技術相關 (
K8S,DevOps,軟體測試…)
如果你覺得內容有幫助,歡迎你點此訂閱我的文章,你的訂閱會帶給我更多動力,持續分享有意義的內容!