当前位置: 首页 > 知识库问答 >
问题:

将用户从Keycloak迁移到密码不变的LDAP

钮瀚
2023-03-14

我们目前有一个Keycloak领域,我们希望将所有现有用户导出到LDAP中(其密码不变),因此我们可以为不支持OpenID Connect或SAML但支持LDAP的其他位置添加登录支持。

由于密码凭据是使用pbkdf2-sha256算法存储在Keycloak MySQL用户数据库中的,所以我必须使用OpenLDAP 2.4.47和contrib模块来支持LDAP端的密码凭据(我也相信我已经在配置中启用了这个模块)。

我在使用这里描述的格式将现有的has(从Keycloak)转移到LDAP时遇到了困难:https://github.com/hamano/openldap-pbkdf2

我尝试使用HASH_ITERATIONS、SALT和VALUE字段,以及PHP手册中base64_encode下的注释中提供的base64url_encode自定义函数,来创建“适应的base64”字符串,并在创建LDAP用户时将构建的字符串作为userPassword字段提供。在LDAP中成功创建了该用户,但我无法使用刚刚创建的用户的凭据对LDAP进行身份验证。

/*
This example migrates a single user, to be adapted to a loop later, if it works.

NOTE: KC_* constants are defined in an external config.php file, such as:
KC_LDAP_BASEDN = "ou=users,dc=sso,dc=example,dc=com"
KC_REALM_ID = "KeycloakUserRealm"
(not actual code from config.php, but you get the point)
*/

$ldc = ldap_connect(KC_LDAP_SERVER);
ldap_set_option($ldc, LDAP_OPT_PROTOCOL_VERSION, KC_LDAP_PROTOCOL); // should be 3 in config.php
$ldb = ldap_bind($ldc, KC_LDAP_BINDDN, KC_LDAP_BINDPW);

$usertest = 'username_of_user_to_be_migrated';

// fetch user info
$u_sel = $db->query("SELECT * FROM `USER_ENTITY` WHERE `USERNAME`='".$db->real_escape_string($usertest)."' AND `REALM_ID`='".$db->real_escape_string(KC
_REALM_ID)."'");

$uinfo = $u_sel->fetch_assoc();

// fetch credential of user, type="password"
$c_sel = $db->query("SELECT * FROM `CREDENTIAL` WHERE `USER_ID`='".$db->real_escape_string($uinfo['ID'])."' AND `TYPE`='password'");

$cred = $c_sel->fetch_assoc();

$uprop = array();
$uprop['objectClass'] = array('top', 'person', 'organizationalPerson', 'inetOrgPerson');
$uprop['uid'] = $uinfo['USERNAME'];
$uprop['mail'] = $uinfo['EMAIL'];
$uprop['cn'] = $uinfo['FIRST_NAME'];
$uprop['sn'] = $uinfo['LAST_NAME'];

// also base64_decode() VALUE, since this seems to be already enocoded in base64, before re-encoding it with base64url_encode()
$uprop['userPassword'] = '{'.strtoupper($cred['ALGORITHM']).'}'.$cred['HASH_ITERATIONS'].'$'.base64url_encode($cred['SALT']).'$'.base64url_encode(base6
4_decode($cred['VALUE']));

ldap_add($ldc, 'uid='.$uprop['uid'].','.KC_LDAP_BASEDN, $uprop);

完成后,我运行第二个脚本尝试与该用户连接:

$ldc = ldap_connect(KC_LDAP_SERVER);
ldap_set_option($ldc, LDAP_OPT_PROTOCOL_VERSION, KC_LDAP_PROTOCOL); // should be 3 in config.php

$userdn = 'uid=username_of_user_to_be_migrated,'.KC_LDAP_BASEDN;
$userpw = 'asdASD123';

$ldb = ldap_bind($ldc, $userdn, $userpw);

在执行上面的第二个脚本时,我只得到:

PHP Warning:  ldap_bind(): Unable to bind to server: Invalid credentials in /home/user/projectdir/test_ldap_user.php on line 22
             ID: 5718a65c-1927-4ac7-87ce-aec0c7dda296
         DEVICE: NULL
HASH_ITERATIONS: 27500
           SALT: � �??�Pz�e��X,
           TYPE: password
          VALUE: DdCJAJvuhidAC2by7TZY8I0E8HF4V6FXrPa4nSXduvSzbb+xHW3D4QiiiPpvuzL2bdk6k0kNQKS/477k5kiLzA==
        USER_ID: b06ce13f-4e8e-474e-b5ee-5d664d6f9575
   CREATED_DATE: 1561051801144
        COUNTER: 0
         DIGITS: 0
         PERIOD: 0
      ALGORITHM: pbkdf2-sha256
{PBKDF2-SHA256}27500$FrcRlj8SGJJQet1l9LNYLA$DdCJAJvuhidAC2by7TZY8I0E8HF4V6FXrPa4nSXduvSzbb-xHW3D4QiiiPpvuzL2bdk6k0kNQKS_477k5kiLzA

或者是否已经有一个迁移脚本/解决方案来处理我还没有找到的KeyCloak->LDAP?

提前感谢你在正确方向上的任何帮助或推动。

共有1个答案

沈博涉
2023-03-14

快速更新:我设法找到了一个解决方案与我的一个优秀的同事一起,我想张贴在这里的解决方案,以供将来的参考,如果有人卡住了这一点。

我们发现,无论使用哪种算法,Keycloak中用于哈希的密钥长度都是64字节。这也意味着,对于那些默认密钥长度小于64字节(使其正好长64字节)的算法,将重复哈希的字节序列。在PBKDF2中,SHA-1的缺省密钥长度为20字节,SHA-256的缺省密钥长度为32字节,SHA-512的缺省密钥长度为64字节。这使我能够创建以下PHP函数,该函数返回与slappasswd返回的字符串类型完全相同的字符串:

// Convert password credentials from Keycloak database to LDAP format (specific to PBKDF2 module)
// Parameter $cred is array from Keycloak database fields for 'CREDENTIAL' table
function password_keycloak_to_ldap($cred) {
        switch (strtolower($cred['ALGORITHM'])) {
                case 'pbkdf2':
                case 'pbkdf2-sha1':
                        $keybytes = 20;
                        break;
                case 'pbkdf2-sha256':
                        $keybytes = 32;
                        break;
                default:
                        $keybytes = 64;
                        break;
        }
        $out = '{'.strtoupper($cred['ALGORITHM']).'}'.$cred['HASH_ITERATIONS'].'$'.ab64_encode($cred['SALT']).'$';
        $oldhash = base64_decode($cred['VALUE']);
        $newhash = substr($oldhash, 0, $keybytes);
        $out .= ab64_encode($newhash);
        return $out;
}

此外,我还设置了附加的helper函数(从其他地方复制):

// ab64_* functions adapted from Python's Passlib v1.7.1
function ab64_encode($data){
        return rtrim(strtr(base64_encode($data), '+', '.'), '=');
}

function ab64_decode($data){
        return base64_decode(strtr($data,'.', '+').str_repeat('=', 3-(3+strlen($data))%4));
}
$uprop['userPassword'] = password_keycloak_to_ldap($cred);
 类似资料:
  • 我正在尝试将用户从旧的Drupal6 CMS迁移到KeyCloak。我想迁移用户与他们的旧密码,然后分配一个“更新密码”要求的行动到他们的个人资料。 然而,迁移密码似乎有问题,因为我只能以散列形式访问它们。 null 有没有人有幸让这个功能发挥作用?

  • 大家好,我正在尝试将一个用户池迁移到另一个用户池。因此,我尝试这样做:https://docs.aws.amazon.com/en_en/cognito/latest/developerguide/user-pool-lambda-migrate-user.html 当将authflow转换为USER\u PASSWORD\u AUTH时,我的密码仍然不在请求中。示例代码: Authenticat

  • 我需要将phpBB3用户迁移到Drupal7。用户必须能够使用他们的phpBB用户名/密码组合在Drupal中进行身份验证。 有没有办法把密码翻译成Drupal7格式?

  • 我们正在将war文件从TOMCAT迁移到IBMWebSphere8.5。5应用服务器。它在TOMCAT上运行良好,但在IBM中抛出“无效用户名/密码登录被拒绝”错误是错误的。我在web中配置了正确的数据源。xml和持久性。xml。我还与我们的服务器管理员进行了检查,他确认数据源是正确的,并且能够使用相同的方法成功地进行测试。不确定是否需要在此处添加/更改IBM WAAS 8.5的任何配置。请告知。

  • 问题内容: 我正在从elasticsearch1.4.3迁移到2.4,并替换了elasticsearch文档中引用的一段代码,而其他参考则需要替换andFilter? 码:- 问题答案: 您可以这样做: