Active Directory "Validate password policy" not working

We want to allow our users to change their Active Directory passwords via Keycloak. We changed the Edit mode of the federation provider to WRITABLE and toggled the Validate password policy switch on. Basic constraints like password length and complexity are enforced, but some of the password constraints set in AD are not enforced:

  • Users can use any previous password although the last three passwords should be forbidden (Password history)
  • Users can immediately change their password again although there should be a 24 hour wait period

This is the same behavior as when Validate password policy was toggled off. Keycloak version is 20.0.1 and AD is running on a Windows Server version that should support the LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID. We are not using AD LDS.

My assumption is that the new admin UI might not be properly triggering the Validate password policy option. Is anyone else experiencing this? Or are we missing some configuration? We tried activating the Enable the LDAPv3 password modify extended operation toggle in addition but that did not change anything.

I read up on the topic and also found a mailing list thread which pointed me to an old JIRA issue for this problem which was fixed. Here is a bit of background I learned on the way. Unfortunately I had to remove some links as new users can only add two links to a post. I replaced links to the source code on GitHub with the file name and line number and will add missing links to a follow up post.

There are two ways to perform a password change in AD (or maybe with LDAP in general). Either the old password is deleted and the new one created (akin to user changing their own password - all constraints are enforced) or the password is replaced (akin to admin changing a user’s password - only basic constraints like password length and complexity are enforced). Keycloak performs a replace operation (LDAPIdentityStore.java#L397) but specifies the additional LDAP_SERVER_POLICY_HINTS control which should cause the additional constraints to be enforced. The reasoning is given in a comment of the aforementioned issue, the article linked in the comment is down but thankfully the Wayback machine has a snapshot of it. Something about the AD control was changed after that article was written so the initial control OID was renamed to LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID and a new OID with the name LDAP_SERVER_POLICY_HINTS_OID exists. The official documentation [1] specifies that the deprecated control was introduced in Windows Server 2008 R2 and the newer control in Windows Server 2012 but both controls are supported at least until Windows Server 2019 (the most recent version listed in that documentation). Keycloak uses the deprecated control for wider support (specified in LDAPServerPolicyHintsDecorator.java#L44). The control is only used for AD (MSADUserAccountControlStorageMapper.java#L77), but not for AD LDS (MSADLDSUserAccountControlStorageMapper.java#L76).

[1] [MS-ADTS]: LDAP Extended Controls | Microsoft Learn

While doing some testing with the legacy admin UI we saw that the information for the Validate Password Policy switch is a little bit more detailed there. According to that info it only turns on/off policy validation on the Keycloak side, so turning it on or off will not make any difference in our case. However, this would mean that the password replacement does not respect the passed OID in general.

Does anyone have user federation set up with AD and is getting the password history policy applied on a password change?