应该使用 ID Token 还是 Access Token 来授权 SPA 功能?

Should the ID Token or Access Token be used to authorize SPA functionality?

上下文

我有一个与后端 REST 通信的单页应用程序 API。这个 REST API 是专门为 SPA 服务的。为了导航或使用 SPA 主页以外的任何功能,用户必须先登录。我将 OIDC 与 Okta 结合使用来对用户进行身份验证。用户可以具有管理员角色或用户角色。他们的角色将用于授权允许他们导航到哪些 SPA 页面,以及允许他们进行哪些 REST API 调用。

问题

  1. 用户登录后,我的应用程序收到来自 Okta 的 ID 令牌和访问令牌。我可以选择将用户角色作为自定义声明包含在 ID 令牌或访问令牌中。哪个令牌应包含此信息?两个?

  2. UI需要根据用户角色做出一些授权决定。 例如,要显示或隐藏哪些 HTML 元素,以及哪些 SPA 路线可导航。这些决定应该通过检查 ID 令牌还是访问令牌来做出?其他?

  3. 当通过 SPA 调用我的后端 API 时,我应该转发我的 SPA 收到的 ID 令牌和访问令牌吗?只是访问令牌?或者我应该为我的后端 REST API 设置一个不同的授权服务器,并让我的 SPA 联系 另一个 访问令牌?

一些答案:

  1. id 令牌只是向 SPA 断言用户已通过身份验证。如果要将角色放在令牌中,请使用访问令牌,其目的是授权

  2. API应该是控制权限。您的 SPA 应该询问您的 API 有关授权区域的信息,并且 API 可以根据访问令牌内容进行回答。您的 SPA 不应直接读取访问令牌。

  3. 仅将访问令牌发送到 API,这是标准的推荐行为

职责

一般:

  • UI 可以 UI 决定显示哪些元素
  • 当然,他们为此使用的数据需要来自可信来源
  • UIs 可以从 id 令牌中读取角色并使用它来控制要显示的内容
  • 但是API还需要角色信息,来授权请求​​

如果您想在 UI 和 API 中使用角色信息,则默认选项是将角色添加到 ID 令牌和访问令牌。

然而,这并不能很好地扩展,因为在真实的商业应用程序中,您可能会随着时间的推移添加多个类似的规则,并且不断需要向令牌添加声明。

可扩展性

随着时间的推移更易于管理的更好选择是 UI 向其 API 询问角色 + 其他数据 - 因为 API 需要相同的角色无论如何信息。

此外,令牌不必是 UI 和 API 做出的授权决策的唯一数据来源。我的 blog post on claims 描述了一种模式,您可以使用它来管理来自多个数据源的索赔。