Uploaded image for project: 'Keycloak'
  1. Keycloak
  2. KEYCLOAK-12340

Regression in CredentialInputUpdater handling (also broken LDAP password update)

    Details

    • Sprint:
      Keycloak Sprint 33, Keycloak Sprint 34
    • Steps to Reproduce:
      1. Create a UserStorageProvider SPI
      2. Implement CredentialInputUpdater
      3. Change the User's password in the Admin Console
    • Docs QE Status:
      NEW
    • QE Status:
      NEW

      Description

      We have a custom UserStorageProvider for our licence database, which also contains passwords. To handle these, we use the CredentialInput(Updater,Validator) interfaces.

      This worked fine when we used Keycloak 6 (we skipped 7, so I currently don't have capabilities to test this if it also affects 7, but I think it does not). In Keycloak 8, there were some changes made in how passwords are handled (among others the introduction of the PasswordCredentialModel class). Ever since we upgraded to Keycloak 8, updating the passwords for users that are stored in our licence database no longer works through the Admin Console (Credentials Tab). It seems like a new password is created for the user in the Keycloak database rather than in our licence database.

      A simple log statement in our updateCredential function seems to indicate that this method never gets called when a password is created in the Credentials Tab. It does however get invoked when the user tries to change their password through the the /auth/realms/(realm)/account/password console, and here the password gets updated as it should in our remote database.

          @Override
          public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
              LOGGER.info("Invoked updateCredential");
              if (input instanceof UserCredentialModel) {
                  UserCredentialModel cred = (UserCredentialModel) input;
                  if (cred.getType().equals(PasswordCredentialModel.TYPE)) {
                      TypedQuery<LicenceDevice> query = em.createNamedQuery("LicenceDevice.findByUid", LicenceDevice.class);
                      query.setParameter("uid", user.getUsername());
                      query.setParameter("realm", realm.getName());
                      LicenceDevice device = query.getSingleResult();
      
                      if (device != null) {
                          String rawPassword = cred.getChallengeResponse();
                          String salt = BCrypt.gensalt(12);
                          String hashedPassword = BCrypt.hashpw(rawPassword, salt);
                          device.setCredential(hashedPassword);
                          em.merge(device);
                          return true;
                      }
                  }
              }
              return false;
          }
      

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  mposolda Marek Posolda
                  Reporter:
                  sonofra Simon Levermann
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  7 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: