在 keycloak 和 spring 中管理用户权限 api

Managing user permissions in keycloak and spring rest api

TL;DR

  • Objective: managing api permissions:
    • OIDC authorization direct grant flow
    • User federation and authentication source : LDAP
    • Permissions store : legacy database
    • Client management and authentication: Keycloak
  • Question: What are the best practices for managing user permissions on Keycloak and rest api?

上下文

我们正在实施 API 和 spring 的休息,以供移动应用程序和 SPA 使用。我们的用户帐户、权限、规则……以及所有数据都存储在不同单体应用程序使用的自定义数据库中。为了保护我们的 api,我们决定使用 Keycloak。

keycloak 服务器配置有用于用户联合的现有 LDAP 和用于移动客户端应用程序的“Direct grand flow”。对于第一个用例(身份验证),一切正常。

现在我们必须按如下方式管理用户权限:

据我所知,keycloak 可以使用硬编码或基于用户的策略来处理授权和细粒度权限,但不能在本地插入不同的授权源。因此,我考虑使用 Keycloak SPI 构建自定义角色映射器,从我将开发的自定义 api 中检索用户权限,然后将它们映射到访问令牌。

因此,我的访问令牌应如下所示:

"resource_access": {
    “My-client”: {
      “permissions”: [
        “Show-products”,
        “Buy-something”,
        “Display-prices”
      ]
    }
  },
  "username": “myUser”

然后移动应用程序应该能够知道基于令牌的用户权限,我的无状态服务器端 (API) 应该能够在每次调用时访问用户权限以使用 [=88 检查它们=] 注释:

@PreAuthorize("hasRole('Show-products')")

问题

在第一次试验后,我的解决方案似乎工作正常,但我仍然对这个选择有一些安全担忧,因为它不符合 keycloak 标准,并且包括对 keycloak 映射器中不同后端的其余调用。

所以我想知道:

补充信息

我正在使用:

关于您的问题:

- 将用户权限放在访问令牌声明上是否安全?

是的,功能可以(而且应该)在访问令牌上,这样您就可以在业务层中做出一些决定(基于 roles/access 声明)。不过请记住,令牌仅采用 base 64 编码,可以被其他人复制和查看,因此它不应该包含秘密或特别机密的信息,通常你会在那里放置足够的关于用户的信息,以及它的一些当前 permissions/capabilities/claims。

如何保护 keycloak 访问外部系统(rest 调用)以检索权限?

这取决于它是否需要从您的网络外部访问。如果没有,你可以让它不受保护(并且 unavailbale from outside/or 仅适用于某些特定的 IP)。如果它可以从 outside/or 获得,你想用 keycloack 保护它,你可以有一个 "confidential" 或 "bearer only" 类型的客户端。我建议您研究 CORS 和令牌共享,这样您就可以将已经创建的 "access-token" 重新用于其他端点,而无需再次进行身份验证。

我是否应该依靠令牌声明来验证用户对资源服务器中每个请求的权限?

不太清楚你的意思。在 keycloak 中,资源服务器不像典型的 oAuth2 舞蹈那样进行额外的资源授权(除非你的策略执行器被激活,但我相信你没有采用这种方法,而是一个映射器 SPI @auth 服务器来让你的角色正确?)

在 oAuth2 中,"resource server" 有 2 个职责:1-提供资源和 2-执行额外的授权步骤。在密钥斗篷世界中,这两个步骤由不同的参与者完成。第 1 步由您的应用程序完成,第 2 步仅在 keycloak 也激活策略执行时才完成(这意味着 Keycloak 是 auth 服务器,也是 "resource server" 从 oAuth2 角度来看的一部分)

现在回到你的问题,如果你所说的资源服务器只是指你的应用程序提供内容,那么是的你可以在那里使用声明,记住声明(和整个访问令牌)是生成的并且是数字化的-由 auth 服务器签名,因此您可以在您的应用程序中毫无问题地使用这些声明(否则也不知道该怎么做)。

是否有任何其他干净的解决方案/最佳实践来处理 keycloak 中来自外部源的用户权限?

很难说,你可能已经注意到了;网络上针对您的特定用例的文档非常有限;因此那里没有很多最佳实践工作,您唯一真正的选择是使用带有自定义策略 SPI 的策略,这会带来其他挑战。我会说你的解决方案很好。

此致。