Understanding Password Policy with Keycloak and LDAP : both Keycloak and LDAP servers provide password policy support.
This article discusses keycloak and Ldap password policies and what is the best route to choose when performing Keycloak/LDAP integration.
The end user should either choose Keycloak Password Policy or LDAP password Policy.
Using a mix of both should be totally ruled out.
1) Using Keycloak password policy
https://www.keycloak.org/docs/latest/server_admin/index.html#_password-policies
1.1) keycloak password policy at realm level
Keycloak password Policy has to be configured at the realm level
1.2) keycloak password policy types
Keycloak defines the following policy types (cf screenshot below) with configurable values, but none of them is enforcedDigits
- The number of digits required to be in the password string.
Lowercase Characters
- The number of lower case letters required to be in the password string.
Uppercase Characters
- The number of upper case letters required to be in the password string.
Special Characters
- The number of special characters like ‘?!#%$’ required to be in the password string.
Not Username
- When set, the password is not allowed to be the same as the username.
Regular Expression
- Define one or more Perl regular expression patterns that passwords must match.
Expire Password
- The number of days for which the password is valid. After the number of days has expired, the user is required to change their password.
Not Recently Used
- This policy saves a history of previous passwords. The number of old passwords stored is configurable. When a user changes their password they cannot use any stored passwords.
Password Blacklist
1.3) When shall keycloak password policy be used ?
When keycloak password policy is used:
- The password policy is enforced/applies to all the user of the realm
- When a user within the realm can originate from different origins (different user federation, identity providers), defining a common password policy provides a unified view of the users with all having/sharing the same password policy.
1.4) Keycloak password policy main limitations
The main limitations of keycloak password policy are:
- No account control mecanism
- granularity which applies to the realm
Those main keycloak password policy limitations are overcome when controlling the password policy at LDAP level.
2) Using LDAP Password policy with keycloak
2.1) LDAP password policy definition
LDAP password policy is defined by Password Policy for LDAP
Directories
(draft-behera-ldap-password-policy-10.txt)
https://tools.ietf.org/html/draft-behera-ldap-password-policy-10
2.2) Configuring LDAP password policy
The configuration of an LDAP password policy s outside the scope of this document, and specific is specific to each LDAP provider
2.3) Keycloak integration with LDAP
-
Users can be can be synchronized/ imported within
Keycloak
(all the attributes mapped, but the password) - User bind authentication is always done against the LDAP
2.4) LDAP errors within keycloak (Default)
By default, when an error is generated at the ldap level, keycloak
reports “Invalid credentials”.
There
is no customization done (but windows) to make the distinguo between
the different errors caes
-
Invalid credentials at keycloak level can correspond to:
- Username or password invalid
- account lockout
- password expired
2.5) Ldap Errors handling within keycloak for Windows
Keycloak defines a class to define a Microsoft AD mapper to handle error codes:
-
MSADLDSUserAccountControlStorageMapper
https://www.keycloak.org/docs-api/6.0/javadocs/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapper.html
When this mapper is enabled, Windows ldap errors messages are intercepted by this corresponding keycloak with the appropriate processing for error handling
AD error code
The AD-specific error code is the one after « data » and before « vece » or « v893 » in the actual error string returned to the binding process 525 user not found 52e invalid credentials 530 not permitted to logon at this time 531 not permitted to logon at this workstation 532 password expired 533 534 account disabled The user has not been granted the requested logon type at this machine 701 account expired 773 user must reset password 775 user account locked |
Keycloak source code to handle MS-AD errors
protected boolean processAuthErrorCode(String errorCode, UserModel user) {
logger.debugf("MSAD LDS Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername());
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
if (errorCode.equals("532") || errorCode.equals("773")) {
// User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action
if (!user.getRequiredActions().contains(UserModel.RequiredAction.UPDATE_PASSWORD.name())) {
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}
return true;
} else if (errorCode.equals("533")) {
// User is disabled in MSAD LDS. Set him to disabled in KC as well
if (user.isEnabled()) {
user.setEnabled(false);
}
return true;
} else if (errorCode.equals("775")) {
logger.warnf("Locked user '%s' attempt to login", user.getUsername());
}
}
return false;
}
Interesting to be noticed that for windows, this corresponding piece of code is able to handle Password reset. The password reset is handled through a specific UseraccessControl, which is UPDATE_PASSWORD.
2.6) Ldap Errors handling within keycloak but windows
As mentioned previously, Keycloak does not implement error handling for other Ldap providers but LDAP MS-AD.
If there was a need to be able to have a specific LDAP error keycloak handing, the user should develop a SPI in the same as what been done with windows (MSADLDSUserAccountControlStorageMapper)
2.7) Password Expiry Date / Updating Password
A point to be careful with is password Expiration, as there is no mechanism, which can set user required action at keycloak level to UpdatePassword.
Another possible way to handle the password expiration date, if specific SPI handling LDAP errors is not developed would be to have an external batch running daily comparing currentDate with passwordExpiryDate and setting the user required action to UpdatePassword if necessary.
3) User LDAP Account Lockout / Keycloak message
After a number of unsuccessful bind attempts Ldap account is
locked.
It is possible to define parameters such as
- Number of possible attempts before locking the account (3 attempts for example)
- Duration of the lockout (1 day for example)
At keycloak level, is only reported the error message invalid user credentials.
Having the same message reported “ invalid user credentials” for user lockout or invalid credentials is something very common, as it doesn’t provide any to hint to potential attackers. Like this they can’t even guess that the account is locked and for how long.
4) Migration and Provisionning of users to a LDAP DataBase
One of the situation often seen, is that the customer wants to migrate transparently existing users to an LDAP, where the users can be in RDMS , old LDAP. Often the password storage scheme used whithin the old system can be very weak (MD5, SHA1 …)
Thanks to keycloak, it is possible to:
- migrate transparently the user with their old password
- force user to reset their password upon first authentication
- new password (created) will be stored with a stronger password scheme (SSHA2 …)
To achieve such a result, keycloak should be configured to force password update as required upon user creation. The new LDAP should also be configured with strong password storage scheme (SSHA2 for example).
- New Keycloak online training - 19 janvier 2022
- Sizing Keycloak or Redhat SSO projects - 8 juin 2021
- Keycloak.X Distribution - 28 janvier 2021