Search code examples
spring-bootwindows-server-2016unboundid-ldap-sdkpassword-policyunboundid

Password policy is not working completely in Windows server 2016 AD while using UnboundID in springboot app


I'm having issues with an AD in Windows server 2016 with a passsword policy like this one:

Password policy for testing purposes

Now in a Springboot app with UnboundID the first issue that I've found is that the Minimum password age rule is being ignored while I change a password, there's no error coming from the AD and the app changes the password correctly, with something like this:

public String changePassword(UserAndPasswordDTO credentials) {
    // Create connection with active directory
    final LDAPConnection connection = this.createADConnection(myHost, Integer.parseInt(port), dn, password);
    if (connection != null) {
        try {
            // Properly encode the password. It must be enclosed in quotation marks,
            // and it must use a UTF-16LE encoding.
            logger.debug("Going to encode the password.");
            byte[] quotedPasswordBytes = null;
            try {
                final String quotedPassword = '"' + credentials.getPassword() + '"';
                quotedPasswordBytes = quotedPassword.getBytes("UTF-16LE");
            } catch (final UnsupportedEncodingException uee) {
                logger.error("Unable to encode the quoted password in UTF-16LE:  "
                        + StaticUtils.getExceptionMessage(uee));
            }
            // Search in active directory
            SearchResult searchResult = connection.search("dc=" + domain + ",dc=com", SearchScope.SUB,
                    "sAMAccountName=" + credentials.getUsername());
            List<SearchResultEntry> searchEntries = searchResult.getSearchEntries();
            if (searchEntries.size() != 1) {
                // The search didn't match exactly one entry.
                logger.debug("Coming out of the change password service");
                return "The search didn't match exactly one entry.";
            } else {
                // Get the dn value of the search
                String userDN = searchEntries.get(0).getAttribute("distinguishedName").getValue();
                // Attempt to modify the user password.
                final Modification mod = new Modification(ModificationType.REPLACE, "unicodePwd",
                        quotedPasswordBytes);
                connection.modify(userDN, mod);
                logger.debug("Coming out of the change password service");
                return "Password changed succesfully";
            }
        } catch (LDAPException e) {
            logger.error("Error when try to search the user to modify his password");
            logger.debug("Coming out of the change password service");
            return "Error when try to search the user to modify his password";
        } finally {
            connection.close();
        }
    } else {
        // Connection to AD is null
        logger.debug("Connection to active directory is null");
        logger.debug("Coming out of the change password service");
        return "Active Directory connection error";
    }
}

In this scenario, should be working Enforce password history too, but it allows to repeat the password, i.e. change password to abc+000 more than 10 consecutive times, meaning that this password history is not generating an error or something. So, here comes my questions... Why is it happening this? and how can i solve it? Any help will appreciated. Thanks!

PD: I tested the Complexity requirements and length rule, and these are working good returning an error for the action in the AD. PD2: The AD is under LDAPS protocol.


Solution

  • You posted this somewhere else but I thought it would be easier to communicate here. I did quick research and found this... It does not provide support for any features related to password policy (e.g., password expiration, account lockout, rejecting weak passwords, etc.). Further, it does not obscure passwords stored in any way, nor does it support the use of passwords that have already been encoded in some form. https://docs.ldap.com/ldap-sdk/docs/in-memory-directory-server.html