目錄

Revocation 與 Introspection

OAuth 2.0 對於授權流程的規範非常清楚,但它僅僅只定義到 client 拿到 token 而已。

但有兩件事並沒有在 RFC 6749 裡定義:

  1. 使用者要如何撤銷授權,也就是讓 token 失去作用
  2. resource server 要如何檢驗 token

這兩件事分別在 2013 年的 RFC 7009 - OAuth 2.0 Token Revocation 與 2015 年的 RFC 7662 - OAuth 2.0 Token Introspection 裡定義。

RFC 7009 定義了 client 要如何主動地撤銷(revocation)授權。以「透過 Facebook 登入 iT 邦幫忙」這個範例為例,在需要做撤銷的時機即為「登出」。因此在登出的時候需要呼叫 Facebook 提供的 revocation endpoint

這是一個非常簡單的協定,直接參考 RFC 7009 的範例:

POST /revoke HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

此 API 需使用 POST 方法,並且必須對 client 做驗證。參數說明如下:

名稱必要說明
tokenREQUIRED想要撤銷的 token
token_type_hintOPTIONALtoken 類型的提示

因為 token 會有多種類型,如 access tokenrefresh token,因此若有提示將有助於授權服務器最佳化處理。而以撤銷的目的來說,不管是成功處理,或是 client 傳了一個無效的 token,授權伺服器皆可回傳給 client 200 的回應。

而相對的若是出現錯誤,則可以參考 RFC 6749 裡面對錯誤回應的定義,RFC 7009 則是多定義了 unsupported_token_type,它代表授權服務無法處理 token_type_hint 所表示的類型(如 refresh token)

類似地,RFC 7662 是定義如何檢查 token 的資訊,就 token endpoint 回傳的資訊畢竟還是不夠用。這個協定定義了一個 API 稱之為 introspection endpoint,它能提供更多 token 的相關資訊。

這個協定也非常簡單,參考 RFC 7662 的範例:

POST /introspect HTTP/1.1
Host: server.example.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token=mF_9.B5f-4.1JqM&token_type_hint=access_token

此 API 需使用 POST 方法,並且必須對 client 做驗證。參數說明如下:

名稱必要說明
tokenREQUIRED想要檢查的 token
token_type_hintOPTIONALtoken 類型的提示

成功回應會是一個 JSON object,因為是檢查,所以回傳的資訊有定義很多:

名稱必要說明
activeREQUIREDtoken 是否還可用
scopeOPTIONAL使用者實際授權的範圍
client_idOPTIONAL是哪個 client 要求授權
usernameOPTIONAL使用者 ID
token_typeOPTIONALtoken 的格式,如 access token
expOPTIONALToken 失效時間
iatOPTIONALToken 發行時間
nbfOPTIONALToken 需要過了這個時間點才能開始使用
subOPTIONAL使用者識別碼
audOPTIONAL允許接受 ID Token 的單位
issOPTIONAL發行單位
jtiOPTIONALJWT 的 ID

其中因為 active 是必填項,代表此 API 可以拿來讓 resource server 做為檢查用。這裡也可以注意到有許多欄位是 JWT 曾看到過的,所以可以聯想得到這個 API 有某種程度是在做類似 JWT 的自我驗證的事。

另外也許有人會好奇,introspection 的使用情境應該比較像 GET,怎麼會用 POST?這是因為 RESTful 在討論的是 guideline,而不是協定或規範,因此考量的點是不同的。舉個例,不管是 OAuth 2.0 或是 OpenID Connect,所有 HTTP 呼叫大多都是 GET 或 POST;編碼都是 application/x-www-form-urlencoded,這主要是為了考慮向下相容性。而至於為何用 POST,推測應該是因為避免讓 access log 出現 token 的資訊。

在整個流程所參與到的角色來說,有 authorization endpointtoken endpoint 或今天提到的兩個 endpoint,都算是授權伺服器來的 metadata,相關訊息是由 RFC 8414 定義的。