探索 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 授權就像是你申請簽證進入一個國家的方式。當簽證頒發給你的時候,你基本上就獲得了進入該國的 "令牌"。
同樣地,當使用一個應用程式時,授權請求是你要求授權伺服器授予你訪問的行動。授權伺服器驗證你的身份,並發給你 "簽證"(訪問令牌),以登入應用程式。
常用的 OIDC 授權類型:
- 授權碼授權:這是 OIDC 最常用的授權類型。它包括將用戶重定向到授權伺服器,獲取授權碼,重定向回應用程式並交換碼以獲取訪問令牌。想像這是從大使館申請簽證以進入外國的標準過程。
- 刷新令牌授權:在 OIDC 中,這種授權類型允許客戶端應用程式使用先前發出的刷新令牌來獲取新的訪問令牌。這常用於延長用戶的會話而不需要重新輸入他們的憑證。想像你的簽證附有一張神奇的卡片,允許你延長在外國的逗留而不必再次通過海關。
- 隱式授權:這種授權類型用於傳統的基於瀏覽器的應用程式,比授權碼授權不那麼安全。它直接將訪問令牌返回給客戶端應用程式。它運作得就像 "落地簽證",因為不需要事先申請簽證。
- 客戶端憑證授權:適合伺服器到伺服器的通訊,這種授權類型允許客戶端應用程式使用其憑證(客戶端 ID 和客戶端密碼)直接與授權伺服器進行身份驗證。這類比一位特工展示一個特殊工作徽章以進入該國,而無需通過簽證申請過程。
授權物件模型:
在 Logto 中,授權作為一個物件實體持久化在資料庫中,包含例如用戶帳戶 ID、應用程式 ID、關聯的 OIDC 資源和範圍、到期時間等資訊。每個刷新令牌和訪問令牌都與一個特定的授權物件關聯。
授權請求:
通過 API 對授權伺服器發出的 HTTP 請求。客戶端應用程式可以向 OIDC 標記端點發出授權請求以達到不同目的,包括申請新的授權(例如,登入並獲取刷新和訪問令牌)、更新授權細節(例如,交換刷新令牌以獲取新的訪問令牌)或撤銷授權(例如,撤銷所有已登入用戶發出的令牌並終止其訪問)。
一個典型的授權碼授權請求如下所示:
理解 "invalid_grant" 錯誤
在 OIDC 中遇到 invalid_grant
錯誤通常表示授權類型或與授權請求相關的資料無效或不被支援。以下是此錯誤的一些常見原因:
- 錯誤的授權類型:對應用程式使用錯誤的授權類型會導致
invalid_grant
錯誤。確保使用 Logto SDKs 使用適當的授權類型。 - 不匹配的重定向 URI:在交換授權碼為令牌時,請求中使用的重定向 URI 必須與初始授權請求中使用的匹配。不匹配可導致
invalid_grant
錯誤。 - 過期或已使用的授權碼:在授權碼登入流程中,授權碼有有限的有效期,一旦用來獲取令牌將被標記為 "已使用"。嘗試交換過期或已使用的碼以獲得訪問令牌將導致
invalid_grant
錯誤。 - 過期或旋轉的刷新令牌:在將刷新令牌交換為訪問令牌時,如果刷新令牌已過期,會發生
invalid_grant
錯誤。此外,為增強安全性,Logto 預設啟用刷新令牌旋轉。使用相同的刷新令牌 第二次請求令牌端點被視為使用 "旋轉" 刷新令牌,將被拒絕。 - 缺失的必需資料或請求標頭:在撰寫授權請求時,必需的參數和請求標頭必須為給定的授權類型提供。例如,客戶端 ID 必須在所有授權請求中提供,客戶端憑證授權需要提供客戶端 ID 和客戶端密碼。通過使用 Logto SDKs 也可減少這個風險。
- 其他原因:由於諸如客戶端憑證不匹配、授權過期或找不到、未找到刷新令牌等原因,也可能發生此錯誤。
排除故障
一些有效地排除 "invalid_grant" 錯誤的提示:
- 始終使用 Logto 客戶端 SDK 將 Logto 整合到你的應用程式中,以確保授權請求正被發送到相應的端點並具有正確的資料。
- 驗證你的應用程式憑證和重定向 URIs 與管理控制台中的配置匹配。
- 避免冗餘請求,特別是對於像 React 和 Vue 的單頁應用程式,頁面組件可能因為依賴變更而重新渲染。確保用於交換代碼或刷新令牌以獲取訪問令牌的功能不會因相同的請求參數多次觸發。這是一些用戶經常犯的錯誤。通常你可以在調試控制台中看到多個 "令牌" 請求,第一個成功但隨後的都失敗,檢查它們的請求參數,看它們是否使用相同的 "代碼" 或 "刷新令牌"。記住,你只能在授權請求中使用一次代碼和刷新令牌。
- 檢查過期時間。例如,如果你的刷新令牌過期(預設 14 天),並收到
invalid_grant
錯誤,你應該適當處理它,重新啟動用戶登入流程。如果你正在使用 Logto SDK,你可以再次調用signIn()
函數將你的用戶重定向回登入頁面。 - 監控審計日誌。前往管理控制台 → 審計日誌,找到與事件相關的錯誤日誌並查看詳細的錯誤堆棧跟蹤。通常,在
invalid_grant
錯誤的堆棧跟蹤中有一個更具體的原因,如 "找不到授權" 或 "刷新令牌過期"。
結尾筆記
invalid_grant
錯誤對初學者來說可能是具挑戰性和令人困惑的,但只要清楚了解 OIDC 授權並注意細節,你可以自己識別並解決該問題。加入我們在 Discord 或 GitHub 的討論,如果這篇部落格幫助澄清了你的困惑並幫助識別你所面臨的問題,請告訴我們。Logto 開發團隊總是樂意協助你。
讓我們一起為你心愛的應用程式打造無縫和安全的身份驗證體驗。