探索 OIDC 授權:理解和排查 "invalid_grant" 錯誤
學習 OpenID Connect (OIDC) 授權的基本知識,以及如何排查 "invalid_grant" 錯誤。
背景
在我們的社群中,我們經常聽到用戶重複提出的一個問題:Logto 中的 "invalid_grant" 錯誤是怎麼回事? 像是 #503
這是一個普遍的挑戰,並且在某些用戶將 Logto 整合到自己的應用程式時成為一個阻礙。然而,這個錯誤的原因在每個案例中都不一樣,有時很難在有限的上下文中解釋。因此,了解精確的 OIDC 概念以及學會如何排查這個問題,對每個人來說都是至關重要的。
現在讓我們深入了解 OIDC 授權的基本知識。
OIDC 授權解釋
如我們在早前的 部落格文章 中所介紹的, OpenID Connect (OIDC) 是建立在 OAuth 2.0 之上的一個協議。
在 OIDC 或 OAuth2 的上下文中, 授權 是使用者(通常是資源擁有者)授予客戶端應用程式的一組權限。授權對於客戶端應用程式訪問用戶的身份信息和其他受保護資源是必須的。OIDC 定義了幾種授權類型,各自適合於不同的場景以及應用程式獲取存取憑證的方式。
這裡有一個類比來幫助你更好地理解 OIDC 授權。
想像你在不同國家旅行,每個國家都要求入境簽證印章。在這個場景中,你的護照就像是你的用戶賬戶,包含你的個人信息。OIDC 授權就像你申請入境簽證的方式。當你獲得簽證時, 你實際上就是獲得了進入該國家的 "token"。
同樣地,使用應用程式時,授權請求就是你向授權伺服器請求授予你訪問許可的行為。授權伺服器驗證你的身份,並向你授予 "簽證"(存取憑證)以登錄到應用程式。
常用的 OIDC 授權類型:
- 授權碼授權:這是 OIDC 中最常用的授權類型。它涉及將用戶重定向到授權伺服器,獲取授權碼,再重定向回應用程式並交換該授權碼以獲取存取憑證。想像成是從大使館申請完成簽證標準過程以進入一個國家。
- 刷新憑證授權:在 OIDC 中,這種授權類型允許客戶端應用程式使用之前發放的刷新憑證獲取新的存取憑證。它通常用於延長用戶的會話,而不需要用戶從新輸入他們的證書。想像你的簽證附帶了一張魔法卡,可以讓你在不經過海關的情况下延長在外國的停留時間。
- 隱式授權:這一授權類型用於傳統的基於瀏覽器的應用程式,相較於授權碼授權不太安全。它直接將存取憑證返回給客戶端應用程式。就像 "落地簽證",因為不需要之前的簽證申請。
- 客戶端憑證授權:適合於伺服器到伺服器的通訊,這種授權類型允許客戶端應用程式直接使用其憑證(客戶端 ID 和客戶端密鑰)自行驗證到授權伺服器。就像特殊探員展示特殊工作證件進入國家而不需要經過簽證申請過程。
授權對象模型:
在 Logto 中,授權在資料庫中作為對象實體保存,包含用戶賬戶 ID 、應用程式 ID 、相關 OIDC 資源和作用域、過期時間等資訊。每個刷新憑證和存取憑證都關聯到一個 特定的授權對象。
授權請求:
通過 API 向授權伺服器發送的 HTTP 請求。客戶端應用程式可以向 OIDC 憑證端點發送授權請求,用於各種目的,包括申請新授權(如登錄並獲取刷新和存取憑證)、更新授權詳情(如交換刷新憑證以獲取新存取憑證)、或撤銷授權(如撤銷發放給已登錄用戶的所有憑證並終止其訪問)。
一個典型的授權碼授權請求如下:
理解 "invalid_grant" 錯誤
在 OIDC 中遇到 invalid_grant
錯誤通常表示授權類型或授權請求的相關資料無效或不受支持。這裡有一些此錯誤的常見原因:
- 錯誤的授權類型:為你的應用程式使用錯誤的授權類型可能導致
invalid_grant
錯誤。確保通過 Logto SDK 使用適當的授權類型。 - 重定向 URI 不匹配:當交換授權碼以獲取憑證時,請求中使用的重定向 URI 必須與最初授權請求中使用的重定向 URI 匹配。不匹配可能導致
invalid_grant
錯誤。 - 授權碼過期或已被消耗:在授權碼登錄流程中,授權碼有其使用期限,並且一旦用於獲取憑證將標記為 "已消耗"。嘗試使用過期或已消耗的授權碼交換存取憑證將導致
invalid_grant
錯誤。 - 刷新憑證過期或旋轉:當使用刷新憑證換取存取憑證時,如果刷新憑證已經過期,會出現
invalid_grant
錯誤。更為,加強安全性,Logto 默認啟用 刷新憑證旋轉。第二次用同一刷 新憑證請求憑證端點,便是使用 "旋轉" 的刷新憑證,將被拒絕。 - 缺少必要資料或請求標頭:在撰寫授權請求時,必須為給定的授權類型提供必要的參數和請求標頭。例如,在所有授權請求中必須提供用戶端 ID ,而在用戶端憑證授權中需提供用戶端 ID 和用戶端密鑰。可通過使用 Logto SDK 緩解此風險。
- 其他原因:錯誤也可能由於用戶端憑證不匹配、授權過期或未找到、刷新憑證未找到等原因導致。
排查
以下是一些有效排查 "invalid_grant" 錯誤的提示:
- 始終使用 Logto 客戶端 SDK 來整合 Logto 到你的應用程式中,以確保授權請求被正確地發送到適當的端點並使用正確的訊息。
- 驗證你的應用資格資訊和重定向 URI 與管理主控台中的設定相匹配。
- 避免製造不必要的請求,特別是對於像 React 和 Vue 這樣的 SPAs,頁面組件可能由於依賴變更而重繪。確保用於將代碼或刷新憑證交換為存取憑證的函數不會使用相同的請求參數被多次觸發。 這是一位我們一些用戶常犯的錯誤。通常如果你能夠在調試主控台中看到多個 "token" 請求,第一個成功但之後的都失敗,檢查它們的請求參數是否使用了相同的 "代碼" 或 "刷新憑證"。記住,你只能在授權請求中使用代碼和刷新憑證一次。
- 檢查過期時間。例如,如果你的刷新憑證過期了(默認為 14 天)並且你收到
invalid_grant
錯誤,你應該正確地處理它,通過重新初始化用戶登錄流程。如果使用 Logto SDK ,可以再次呼叫signIn()
函數讓用戶重定向至登錄頁面。 - 監控審計日誌。前往管理主控台 → 審計日誌,找到與事件相關的錯誤日 誌並檢查詳細錯誤堆疊跟蹤。通常在堆疊跟蹤中有
invalid_grant
錯誤的更具體原因,如 "授權未找到" 或 "刷新憑證過期"。
結束語
invalid_grant
錯誤對初學者來說可能很具挑戰性和困惑,但只要對 OIDC 授權有清晰的理解並注意細節,就可以自己識別並解決該問題。在 Discord 或 GitHub 上加入我們的討論,告訴我們這篇部落格是否有助於釐清疑惑並確定你所面對的問題。Logto 開發團隊總是很樂意協助你。
讓我們一起為你心愛的應用程式建立一個無縫且安全的驗證體驗。