关于安全:Keycloak:用户基于角色的客户端登录访问限制

Keycloak: Role based client log-in access restriction for users

我正在尝试使用 keycloak 实现基于角色的客户端应用程序(VueJS 多页应用程序)控制的相当简单的用例。

Client

如图所示,我在单个领域中有三个不同的角色和三个不同的客户端。
图中的箭头代表哪个角色可以访问哪个客户端。

所以我的主要目标是,

  • 具有角色 Viewer 的用户应该只能登录到 Viewer Application。如果同一用户尝试访问 Operator ApplicationAdmin application,则 keycloak 应该简单地拒绝该用户这样做。
  • 对于具有 AdminOperator 角色的用户,应遵循相同的规则。 Admin 角色的用户应该能够通过 keycloak 登录到这些应用程序中的任何一个。

为了实现这个用例,我尝试了以下方法,

  • 首先通过适当的角色映射到用户和在客户端创建角色。在这种情况下,我先创建领域级别角色,然后创建客户端级别角色,然后将适当的角色分配给在用户部分中创建的用户。
  • 启用 Authorization。在策略中,我删除了授予所有用户访问客户端的默认策略。并创建 User 策略和 Client 策略来限制对客户端应用程序的访问
  • 还尝试使用基于 Group 的授权策略。在这种情况下,我创建了一个具有客户端角色的组,然后将用户分配到这些组。并从 Authorization 组策略启用它们。

但是,不幸的是,这些都不起作用。这意味着我的具有 Viewer 角色的用户可以登录到我的管理应用程序。这很奇怪。


您无需扩展即可执行此操作。

  • 复制所需的流程(例如浏览器流程)
  • 创建一个新的子流(例如用于浏览器表单)并将其命名为 Access By Role 并选择 generic 作为类型。
  • 对于新的子流,请确保在流概览中选择了 CONDITIONAL
  • 对于新的子流程添加执行 Condition - User Role,使其成为 REQUIRED 并配置它:

    • 别名:admin-role-missing
    • 角色:管理员(或任何你的角色)
    • 否定:正确
  • 添加另一个执行: Deny Access 并使其成为 REQUIRED

最终结果应该类似于:
enter

如果条件"admin-role-missing"为真,这将拒绝访问。

您还可以从文档中了解更多信息:explicit-deny-allow-access-in-conditional-flows

另外,不要忘记转到您的客户端并在身份验证覆盖中选择流程。


我使用 KeyCloak 扩展 SPI 解决了几乎相同的问题。部署后,您将在可用的身份验证流中拥有额外的可配置"执行",名为"验证用户角色"。

身份验证流程如下所示:
example

此执行必须放在"用户名密码表单"(或其他对用户进行身份验证的表单)之后,否则身份验证将失败。

源代码在这里:
https://github.com/ValentinChirikov/kc_user_role_validate_extension


最终在应用程序级别处理了这个问题,因为它从 keycloak 端开始不起作用。

登录后,检查 keycloak 对象,检查该对象,我们可以找到在上述问题中提到的配置期间设置的一些有用属性。整体代码如下所示,

1
2
3
4
5
6
7
8
9
10
11
12
13
let appName = 'your_app';
keycloak.init({ onLoad: 'login-required' }).success(function () {
  // Confirm the role & authentication of the user
  if (keycloak.authenticated && keycloak.tokenParsed.resource_access &&
      keycloak.tokenParsed.resource_access.hasOwnProperty(appName)) {
    // Continue with the app execution...
  } else {
    // Logout user
    keycloak.logout();
  }
}).error(function () {
  keycloak.logout();
});

通过这种方式,我设法将未经授权的用户路由出应用程序。

解决方案不是所问问题所要求的,但它有效。虽然我认为这应该在 keycloak 级别本身处理。