跳至主要內容
Skip to content

OAuth 2.0 解決什麼問題

OAuth 2.0 很常被說成「第三方登入」,但這其實只說到它常見用途的一部分。OAuth 2.0 的核心不是登入,而是授權委託:使用者如何允許某個應用,在不交出自己帳號密碼的情況下,存取另一個服務上的受保護資源。

一句話回答:OAuth 2.0 是 RFC 6749 定義的授權框架,解決的是 delegated authorization:Resource Owner 授權 Client 存取 Resource Server 上的資源,Authorization Server 負責取得授權並簽發 Access Token;Client 之後用 Access Token 存取 API。OAuth 2.0 本身不是身份驗證協議,若要做登入與身份資訊,通常要使用建立在 OAuth 2.0 上的 OpenID Connect。


一、 必考觀念

1. OAuth 2.0 解決「不要把密碼交給第三方」

沒有 OAuth 以前,第三方應用如果想讀你的資料,可能會要求:

text
請輸入你的 Google 帳號密碼,我幫你讀取 Calendar。

這非常危險:

  • 第三方拿到你的完整密碼。
  • 使用者無法限制第三方只能讀 Calendar。
  • 撤銷存取很困難。
  • 第三方可能保存密碼。
  • 密碼外洩會影響整個帳號。

OAuth 2.0 的想法是:

text
使用者在原服務授權
-> 第三方拿到有限權限的 access token
-> 第三方不用知道使用者密碼

2. OAuth 2.0 是授權,不是身份驗證

OAuth 2.0 的核心問題:

text
Client 能不能代表使用者存取某個資源?

不是:

text
這個使用者是誰?

如果要登入身份資訊,例如 user id、email、profile,通常要用 OpenID Connect。

簡化:

協議核心
OAuth 2.0授權存取 API
OpenID Connect在 OAuth 2.0 上加入身份層

延伸讀:身份驗證、授權與身份識別的差異

3. OAuth 2.0 是框架,不是單一流程

RFC 6749 定義的是 authorization framework。

它包含:

  • 角色。
  • Token。
  • 授權流程。
  • Grant types。
  • Extension points。

但很多安全細節在後續 RFC 與 Best Current Practice 裡逐步補強,例如 PKCE、refresh token rotation、redirect URI 精確匹配等。

RFC 9700 是 OAuth 2.0 Security Best Current Practice,整理了現代 OAuth 實作應遵守的安全建議。


二、 四個角色

1. Resource Owner

資源擁有者,通常是使用者。

例如:

text
你擁有自己的 Google Calendar 資料。

2. Client

想要存取資源的應用。

例如:

text
一個會幫你整理行程的第三方 App。

Client 不是瀏覽器本身,而是那個應用。

3. Authorization Server

負責:

  • 驗證使用者。
  • 呈現授權頁。
  • 取得使用者同意。
  • 簽發 access token。
  • 簽發 refresh token,視情況。

例如:

text
accounts.google.com

4. Resource Server

真正保存 API 資源的服務。

例如:

text
Google Calendar API

Client 拿 access token 呼叫 Resource Server。


三、 OAuth 2.0 流程總覽

1. Authorization Code Flow

現代 Web / SPA / Mobile 常用 Authorization Code Flow,並搭配 PKCE。

2. 為什麼不用密碼?

Client 不接觸使用者在 Authorization Server 的密碼。

使用者只在 Authorization Server 登入:

text
Client -> redirect 使用者到 Authorization Server
使用者 -> 在 Authorization Server 登入與授權
Authorization Server -> 回 code 給 Client
Client -> 用 code 換 token

這就是 delegated authorization。

3. Authorization Code 是一次性中介物

Authorization code:

  • 短效。
  • 單次使用。
  • 不能直接呼叫 API。
  • 用來換 access token。
  • 應綁定 redirect URI、client、PKCE。

不要把 authorization code 當 access token。


四、 Access Token 與 Scope

1. Access Token 代表授權結果

Access Token 可以理解成:

text
Authorization Server 給 Client 的 API 存取憑證。

Client 呼叫 API:

http
GET /calendar/events
Authorization: Bearer access_token

Resource Server 驗證 token 後,決定是否允許。

延伸讀:Access Token 與 Refresh Token

2. Scope 限制存取範圍

Scope 表示授權範圍:

text
calendar.read
calendar.write
profile.read

使用者授權時看到:

text
這個 App 想讀取你的 Calendar。

Scope 的價值是最小權限:

text
只要讀取,就不要給寫入。

3. Scope 不是你的系統全部權限模型

OAuth scope 通常用來限制 client 對 API 的存取範圍。

但系統內部仍可能有:

  • RBAC。
  • ABAC。
  • 資料權限。
  • 租戶權限。
  • feature flag。

Scope 是授權的一層,不是所有權限問題的唯一答案。


五、 Redirect URI 與 State

1. Redirect URI 很重要

Authorization Server 授權後會導回 Client:

text
https://client.example.com/oauth/callback?code=...

如果 redirect URI 驗證不嚴格,攻擊者可能把 code 導到自己的網站。

安全要求:

  • 預先註冊 redirect URI。
  • 精確匹配。
  • 不使用開放重導向。
  • 不接受任意 wildcard。
  • HTTPS。

RFC 9700 也強調 redirect URI 驗證與防止 authorization code 被攔截的重要性。

2. State 防 CSRF

Client 發起授權時帶:

text
state=random-value

Callback 回來時檢查:

text
received state === stored state

用途:

  • 防止 OAuth login CSRF。
  • 綁定使用者這次發起的 OAuth 流程。
  • 可保存 redirect intent,但要避免塞敏感資料。

3. State 不等於 PKCE

機制解決問題
state防 CSRF、綁定這次授權流程
PKCE防 authorization code 被攔截後換 token

兩者都重要。


六、 PKCE

1. PKCE 解決什麼?

PKCE 是 Proof Key for Code Exchange。

它主要防止:

text
authorization code 被攔截
-> 攻擊者拿 code 去換 token

Client 在開始流程時產生:

text
code_verifier
code_challenge = base64url(sha256(code_verifier))

授權請求帶 code_challenge

換 token 時提交 code_verifier

Authorization Server 驗證兩者是否匹配。

2. 為什麼 SPA / Mobile 需要 PKCE?

SPA / Mobile 是 public client:

  • 不能安全保存 client secret。
  • 程式碼可能被使用者看到。
  • redirect URI 可能被攔截。

所以不能靠 client secret 保護 code exchange。

PKCE 讓 code 即使被截獲,也沒有 code_verifier 就不能換 token。

3. 現代 OAuth 應預設使用 PKCE

RFC 9700 建議 authorization code grant 應使用 PKCE。對 public clients 更是必要。

下一篇第三方登入 / PKCE 專題會更深入展開。


七、 Grant Types

1. Authorization Code

最推薦的互動式授權流程。

現代實務:

text
Authorization Code + PKCE

適合:

  • Web app。
  • SPA。
  • Mobile app。
  • 第三方登入基礎流程。

2. Client Credentials

用於 machine-to-machine。

text
service A -> service B

沒有使用者參與。

適合:

  • 後端服務存取 API。
  • Batch job。
  • Server-to-server integration。

3. Device Authorization Grant

適合輸入受限裝置:

  • TV。
  • CLI。
  • IoT。

使用者在另一台裝置完成授權。

4. Resource Owner Password Credentials 不建議

ROPC 讓 Client 直接收使用者帳密:

text
Client 收 user password
-> 拿去換 token

這違背 OAuth 最初想避免「第三方拿到使用者密碼」的目的。現代實務通常不建議使用。

5. Implicit Flow 已不建議

Implicit Flow 會直接從 front-channel 回 access token。

現代 SPA 應使用:

text
Authorization Code + PKCE

RFC 9700 也不建議使用 implicit grant。


八、 OAuth 和第三方登入的關係

1. 第三方登入通常是 OIDC

當你看到:

text
用 Google 登入

真正用來拿身份資訊的通常是 OpenID Connect。

OAuth 2.0 給你 access token,讓你存取 API。

OIDC 會提供:

  • id token。
  • userinfo。
  • subject。
  • profile claims。

2. 只用 OAuth access token 不一定知道使用者是誰

OAuth access token 可以表示:

text
這個 Client 可以讀某些 API。

但它不一定是給 Client 當登入身份資訊用。

如果 Client 想登入使用者,應使用 OIDC。

下一篇會專門寫 OpenID Connect 與 OAuth 的差異。

3. 第三方登入後仍要有本地帳號

你的系統通常還是要建立:

text
local user
external identity mapping
local session
local authorization

OAuth / OIDC 解決的是外部身份與授權流程,不會自動替你設計本地會員系統。


九、 常見錯誤

1. 把 OAuth 當登入協議

OAuth 2.0 本身是授權框架,不是身份驗證協議。

要做登入應使用 OIDC。

2. 不驗 state

不驗 state 會增加 login CSRF 與流程混淆風險。

3. Redirect URI 開太寬

例如:

text
https://client.example.com/*

或允許任意 redirect。

這會讓 authorization code 洩漏。

4. SPA 使用 implicit flow

現代 SPA 應使用 Authorization Code + PKCE,不應再用 implicit flow。

5. 把 access token 當萬用身份資料

Access token 的 audience 可能是 Resource Server,不一定是 Client。Client 不應隨便 decode access token 當登入 profile。

6. Scope 設太大

不該只要求:

text
all
admin
full_access

應該按功能拆 scope,遵守最小權限。


十、 追問題庫

Q1:OAuth 2.0 解決什麼問題?

OAuth 2.0 解決 delegated authorization:第三方應用如何在不取得使用者密碼的情況下,經使用者授權後,用 access token 存取 Resource Server 上的受保護資源。

Q2:OAuth 2.0 是登入協議嗎?

不是。OAuth 2.0 是授權框架。登入身份層通常由 OpenID Connect 提供。

Q3:OAuth 2.0 四個角色是什麼?

Resource Owner、Client、Authorization Server、Resource Server。

Q4:Scope 是什麼?

Scope 是 access token 的授權範圍,例如 read/write 權限。它限制 Client 能對 Resource Server 做什麼。

Q5:State 和 PKCE 差在哪?

State 防 CSRF 與綁定流程;PKCE 防 authorization code 被攔截後被攻擊者拿去換 token。

Q6:為什麼不建議 Implicit Flow?

因為 access token 直接經 front-channel 回到瀏覽器,暴露風險高。現代 SPA 應使用 Authorization Code + PKCE。


十一、 實作題

題目:設計 OAuth 授權請求

需求:

  • Client 要存取使用者 Calendar。
  • 使用 Authorization Code + PKCE。
  • 要防 CSRF。
  • 授權後回 callback。

建立授權 URL:

typescript
function createAuthorizationUrl() {
  const state = randomString()
  const codeVerifier = randomString()
  const codeChallenge = sha256Base64Url(codeVerifier)

  oauthStateStore.save({
    state,
    codeVerifier,
    redirectAfterLogin: '/settings/integrations',
  })

  const params = new URLSearchParams({
    response_type: 'code',
    client_id: 'client_123',
    redirect_uri: 'https://app.example.com/oauth/callback',
    scope: 'calendar.read',
    state,
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
  })

  return `https://auth.example.com/authorize?${params.toString()}`
}

Callback:

typescript
async function handleCallback(query: CallbackQuery) {
  const saved = oauthStateStore.get(query.state)

  if (!saved) {
    throw new InvalidStateError()
  }

  const tokenResponse = await oauthClient.exchangeCode({
    code: query.code,
    redirectUri: 'https://app.example.com/oauth/callback',
    codeVerifier: saved.codeVerifier,
  })

  await integrationRepository.saveToken({
    accessToken: tokenResponse.access_token,
    refreshToken: tokenResponse.refresh_token,
    scope: tokenResponse.scope,
  })
}

重點:

  • state 必須驗。
  • code_verifier 不進 URL。
  • redirect_uri 要和註冊值一致。
  • scope 只要求需要的權限。

十二、 資深視角

1. OAuth 是授權邊界設計

成熟回答要能說:

text
誰授權?
授權給誰?
可以存取什麼?
token 給誰用?
如何撤銷?
如何限制 scope?

不是只說「跳到 Google 登入再 callback」。

2. OAuth 安全細節很多

至少要注意:

  • redirect URI 精確匹配。
  • state。
  • PKCE。
  • scope 最小化。
  • access token audience。
  • refresh token rotation。
  • secret 管理。
  • 不使用 implicit flow。
  • 不使用 ROPC。

這些是現代 OAuth 實作的基本安全要求。

3. OAuth 不取代本地授權

OAuth provider 告訴你:

text
外部授權結果

你的系統仍要處理:

  • 本地使用者。
  • 本地角色。
  • 本地權限。
  • 租戶。
  • 資料範圍。
  • audit log。

不要把外部 token 當成內部全部權限。


總結

問題回答重點
OAuth 解決什麼第三方委託授權,不交出密碼
四個角色Resource Owner、Client、Authorization Server、Resource Server
Access TokenClient 用來存取 Resource Server
Scope限制 token 可做什麼
Authorization Code短效中介物,用來換 token
State防 CSRF、綁定流程
PKCE防 code 被攔截後換 token
OAuth vs OIDCOAuth 授權,OIDC 提供身份登入層
現代建議Authorization Code + PKCE,不用 implicit / ROPC

一句完整的面試回答可以是:

OAuth 2.0 解決的是委託授權問題:使用者不需要把自己在 Resource Server 的帳號密碼交給第三方 Client,而是在 Authorization Server 上登入並授權,Authorization Server 簽發 access token 給 Client,Client 再用 access token 存取 Resource Server 上被授權的資源。OAuth 2.0 有四個角色:Resource Owner、Client、Authorization Server、Resource Server。Scope 用來限制授權範圍,Access Token 代表授權結果。現代互動式流程通常使用 Authorization Code + PKCE,並搭配 state 防 CSRF、redirect URI 精確匹配、防止 code 攔截。OAuth 2.0 本身不是登入協議,如果要取得使用者身份資訊,應使用 OpenID Connect。

延伸閱讀