Web Services 基于用户属性的Keycloak Web服务访问控制

deyfvvtc  于 2022-11-15  发布在  其他
关注(0)|答案(3)|浏览(151)

我花了很多时间试图找到一种方法来基于用户组或角色来限制对由Keycloak保护的Web服务的访问。我得到的最接近的解决方案是实现一个自定义的验证器脚本来执行用户属性检查,但是这个解决方案有一个很大的缺点:您将失去SSO功能。
我使用了以下身份验证器脚本:

AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

 function authenticate(context) {
    var allowed_groups = ['foo', 'bar'];
    var username = user ? user.username : "anonymous";
    var groups = user.getGroups();
    var group_array = groups.toArray();
    
    for (var i in group_array) {
        var gn = group_array[i].getName();
        if (allowed_groups.indexOf(gn) >= 0) {
            LOG.info("Access granted for user '" + username + "' for being member of LDAP group '" + gn + "'");
            return context.success();
        }    
    }

    LOG.info("Access denied for user '" + username + ". for not being member of any of the following LDAP groups: " + allowed_groups);
    context.failure(AuthenticationFlowError.IDENTITY_PROVIDER_DISABLED, context.form().setError(
        "User doesn't have the required LDAP group membership to view this page", null).createForm("error.ftl"));
    return;
 }

认证流程截图:

不幸的是,自定义身份验证器脚本中的用户对象只有在“Username Password Form”身份验证部分通过时才会被填充,否则用户对象为空,因此您无法检查用户属性(如组或角色)。这意味着用户每次都必须为每个客户端键入其凭据(web服务)他打算通过Keycloak访问。不幸的是,没有SSO功能对我们来说不是一个选择,因为我们正在运行10多个web服务。
是否有任何方法可以通过Keycloak实现基于用户属性的客户端访问限制,同时仍然具有SSO?我想知道在“Cookie”auth部分通过后,是否可以以某种方式检索用户信息?我使用的是Keycloak版本11.0.2

zwghvu4y

zwghvu4y1#

到目前为止,您的脚本看起来不错。要重新获得SSO功能,您只需要稍微调整一下流程。将流程拆分为两个子流程(身份验证和授权)非常重要。下面我链接了我的系统中的一个示例。这样,即使通过cookie或Kerberos进行登录,角色检查也能正常工作。
Login Flow for full SSO
我还基于Composite Roles构建了我的脚本。这样我就可以轻松地将客户端与所需的角色链接起来。如果您有多个客户端,而这些客户端应被限制为不同的角色,那么就不需要为每个客户端创建单独的流。

AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

    var client = session.getContext().getClient();
    var clientRole = client.getRole("feature:authenticate");

    if (!user.hasRole(clientRole)) {

        LOG.info("Access to client " + client.getName() + " denied for user " + user.username + " for not being member of the required access role");
        context.failure(
            AuthenticationFlowError.IDENTITY_PROVIDER_DISABLED,
            context.form().setError("You are not authorized to use " + client.getName() + ". Please contact the helpdesk if you need access.", null)
            .createForm("error.ftl"));
        return;
    }

    context.success();
}

然后,您只需在要限制的客户端中创建“功能:authenticate”(脚本中指定的名称)角色...
Role in the client configuration
...并将领域角色(在我的例子中是从LDAP服务器导入的)链接到上面创建的客户端角色:
Link client role to realm role

pkmbmrz7

pkmbmrz72#

您的方法是错误的。身份提供商(例如,使用OIDC协议的Keycloak)提供身份验证,而不是授权。应在应用程序代码中完成授权。应用程序代码必须根据访问令牌中提供的用户详细信息确定是否授权已通过身份验证的用户执行操作(例如,您的群组成员资格,因此用户组必须在Keycloak生成的访问令牌中可用-您已经在Keycloak中通过role-ldap-mapper/group-ldap-mapper对它提供了本机支持)。用您方法测试黑客身份验证过程。

35g0bw71

35g0bw713#

很多答案,但我认为他们没有抓住重点。Keycloak只是一个ID提供者。它说明谁是用户,用户属于什么角色。决定哪些角色可以做什么是应用程序的任务。例如,哪些角色的用户可以登录到管理区域。

相关问题