Search code examples
javaspringldapkeycloakopenldap

Keycloak email "UPDATE_PASSWORD" mechanism with LDAP enabled(15.0.2)


I have a keycloak-server and service which uses it for authentication. I would like to allow users to change their passwords. But it's not clear from the documentation how does email action "Update Password" work with LDAP enabled. https://www.keycloak.org/docs/latest/server_admin/#_user-storage-federation

"By default, Keycloak will import users from LDAP into the local Keycloak user database. This copy of the user is either synchronized on demand, or through a periodic background task. The single exception to this is the synchronization of passwords. Passwords are never imported. Their validation is always delegated to the LDAP server"

and in the Edit Mode section

"WRITABLE Username, email, first name, last name, and other mapped attributes and passwords can all be updated and will be synchronized automatically with your LDAP store."

My settings in the tab "User Federation" -> LDAP are:

"Import Users": "ON",
"Edit Mode": "None"

Sync Settings
"Periodic Full Sync": "Off",
"Peroidic Changed Users Sync": "On"

In the Section "Mappers"
"password" param is not listed.

So, is it correct that if we apply to user email action "UPDATE_PASSWORD" and user will set the new password, the result will be persisted to Keycloak and openldap afterwards? But only if the "Edit mode" on ldap will be set to "WRITABLE"? And in case now, without this mode I will change the password in keycloak, the data will be corrupted because of inconsistency with ldap. Also, I didn't create this keycloak-server, setting the edit mode to "WRITABLE" on LDAP is considered a bad practice/vulnerability? In that case the workaround would be to write the password directly to openldap?

Right now I update the password in such way, but tested it without ldap enabled

 public void updatePassword(String id){
            UserResource userResource = keycloak.realm(keycloakProperties.getRealm())
                    .users().get(id);
            userResource.executeActionsEmail(List.of("UPDATE_PASSWORD"));
        }

Service uses Spring with "keycloak-admin-client" dependency(v. 15.0.2)


Solution

  • Turns out to be as simple as documentation says. If "Edit mode" on LDAP is set to WRITABLE, the new password will be synchronized automatically with your LDAP store. I decided to go with updating "userPassword" directly in openldap and don't have keycloak instance which both reads and writes user data. Also in my case, the updated password format is "plain text". Enabled encoding using certificates from this guide https://github.com/osixia/docker-openldap/issues/208

    policy.ldif

    dn: cn=module{0},cn=config
    changetype: modify
    add: olcModuleLoad
    olcModuleLoad: ppolicy 
    

    overlay.ldif

    dn: olcOverlay={2}ppolicy,olcDatabase={1}mdb,cn=config
    objectClass: olcOverlayConfig
    objectClass: olcPPolicyConfig
    olcOverlay: {2}ppolicy
    olcPPolicyHashCleartext: TRUE