JWT不是為了授權而設計的,只是用作身份驗證。
JWT 主要用於驗證身份。由於大多數開發人員不會開發自己的身份驗證解決方案,因此身份驗證提供商的 SDK 可能會為您完成此操作。您最終從 JWT 獲得的是身份本身。
這很好,因為 JWT 是可驗證的使用者配置檔案的最佳來源。因此,您可能不需要親自驗證 JWT,但您可以並且應該將其用作使用者身份的真實來源。
除此之外,您還可以使用 JWT 來擴充套件身份驗證提供程式的功能。由於 JWT 是可自我驗證的,因此您可以將其用於其他服務,而無需您的身份驗證服務參與。
例如,這意味著您可以建立一個內部 OAuth 伺服器,讓開發人員以更安全可靠的方式使用內部資料。您還可以在共享 API 身份驗證或機器對機器身份驗證時使用 JWT,因為 JWT 是可驗證的。
底線 - JWT 應該用於驗證,並作為使用者身份和使用者資料的真實來源。
JWT 不是什麼
使用者登入並完成身份驗證過程後,我們將進入授權階段 - 決定使用者在我們的應用程式中可以做什麼或不能做什麼。在此步驟中,我們唯一可驗證的是基於 JWT 的使用者身份。
JWT 的主要組成部分是其有效負載,其中包含我們可以識別的使用者 ID。由於授權與身份驗證緊密相關,因此使用者不斷在此有效負載中儲存越來越多的資料。
為了使事情變得簡單且不付出太多努力,許多開發人員決定檢索 JWT 中的屬性並將其與應用程式中的命令式程式碼配對。這通常會導致出現類似“如果 JWT 角色等於某項,則允許/拒絕某項”的語句。有時,當他們想要建立更動態的東西時,他們會新增一個外部函式來根據 JWT 獲取角色。
這是因為許多開發人員將 JWT 的可驗證性質視為適合驗證許可權的東西。
正如我們前面提到的,大多數開發人員在需要處理使用者授權時首次接觸 JWT。大多數開發人員並不真正瞭解驗證過程,最終由身份驗證服務為您提供 JWT。
此時,由於 JWT 可以承載一些定義應用程式中許可權的基本範圍和宣告,許多開發人員傾向於認為,“現在使用者已經透過驗證,我可以使用此令牌來定義使用者應該擁有什麼訪問許可權”。
雖然角色和宣告在我們的應用程式許可權中扮演著重要的角色,但它們不足以完全定義它們。將 JWT 視為授權元件的這種做法存在兩個問題:
- 雖然 JWT 是過去幾年軟體開發領域最偉大的發展之一,但它們並不用於授權。
- 使用 JWT 作為管理應用程式內使用者訪問的唯一方法可能會對應用程式的安全性造成災難性的後果。
JWT 是靜態的
從授權角度來看,我們可以立即看到這種方法過於靜態。讓我們以基於角色的訪問控制 (RBAC) 為例。在 RBAC 中,我們扮演使用者的角色並確定他們是否可以執行特定操作或動作。RBAC 並不止於角色 - 即使像 RBAC 這樣簡單的授權模型也包含更多元件,例如使用者嘗試執行的操作以及他們正在執行該操作的資源。
JWT 僅包含這三個元件的第一部分——使用者及其可能分配的角色。如果將使用者角色作為 JWT 的一部分傳遞,則無法建立動態角色,從而使我們的授權層完全靜態。這意味著在令牌過期之前,過期的許可權將一直有效。
例如,如果我有一個管理員使用者,我想將其降級為標準使用者,除非撤銷 JWT,否則我無法這樣做。由於 JWT 原則上是可驗證的,因此在令牌過期之前無法撤銷它。
通常,現在的 JWT 的生存期非常短,因此對於訪問令牌,TTL(生存時間)可能約為 60 秒,並且 SDK 會為您重新整理它們。因此,我們不能僅僅依賴 JWT 上的角色。
JWT 不夠細粒度
由於 JWT 僅包含有關個人使用者的資訊,因此您可以(並且應該)在其中儲存的資料量有非常嚴格的限制。對於基於屬性的訪問控制 (ABAC)和基於關係的訪問控制 (ReBAC)等模型,使用 JWT 直接建立授權查詢變得不可能。
JWT 有大小限制。這意味著,如果我們想授予使用者訪問 1000 個檔案的許可權,就必須建立一個 20,057 個字元的 JWT — — 這還只是考慮到一個簡單的檔名。如果使用完整路徑名,那麼長度會更長。
設計授權層的第一步是確定需要管理訪問許可權的資源。每種型別的資源及其在應用程式整體結構中的位置可能要求您使用不同型別的授權模型(RBAC、ABAC、ReBAC 或它們的組合)。使用 JWT 可能是一種快速的臨時解決方案,但它遠非可持續。
重要的是,你 要熟悉現有的策略模型、它們的優缺點,並嘗試評估哪些模型最適合你的應用
JWT 在授權中應該扮演什麼角色?
JWT 並非用於授權,而是用於驗證、交換令牌和基於令牌的身份驗證。如果我們按照 JWT 的本意使用它們,即作為使用者身份的真實來源,那麼我們就可以利用它們向外部授權服務查詢使用者可以做什麼或不能做什麼。但是,這種使用不應將任何授權邏輯作為 JWT 本身的一部分。