When using an LDAP directory server to authenticate users, the vast majority of those authentications will make use of a password. Even though the Ping Identity Directory Server supports multiple options for two-factor authentication, you’re still likely to use a password as one of those factors. As such, ensuring that you have a good password policy in place is an essential element of your server’s security configuration.
Obviously, the biggest risk when using password-based authentication is that someone will provide the correct credentials for an account that isn’t theirs, and will be able to do whatever the account owner can do. Some of the most common ways that this can happen are:
The account has a really simple, easily guessable password. Maybe they use the word “password” or some other common value. Maybe their password is the same as their username or email address. Maybe their password is the same as your application or service.
The account owner used the same username and password across multiple sites, and one of those other sites got breached. When this happens, attackers often try to use the breached credentials to log into other sites.
An attacker managed to get access to the encoded representation of a user’s password and was able to crack it through some means.
Some of these are things that are out of your control as a website owner. For example, no matter how careful you are with your own site, you can’t prevent some other site from getting breached and its credentials exposed. However, you can take steps to ensure that your site is better protected against these kinds of things. In this post, I’ll discuss options for creating a password policy that will help keep your site as safe as possible.
While some of the recommendations I provide here are specific to the Ping Identity Directory Server, there is a lot of generic advice in here as well, and that may be applicable to other types of directory servers.
Require Secure Communication
Most LDAP authentication schemes that involve a password send that password to the server in the clear, without any kind of encoding or transformation. There are some that do try to obscure the password (e.g., salted challenge-response authentication mechanisms), but they are typically garbage that actually dramatically weaken the security of your environment and should be avoided at all costs. All of the best password-based authentication mechanisms send the password in the clear, which means that you must ensure that all of the communication happens over a secure, encrypted connection.
The server offers a few options to help ensure that this is done. They are as follows, in order of strongest protection to weakest protection:
Disable any connection handlers that allow insecure communication. If you only allow LDAPS and not unencrypted LDAP, then there is no chance that someone with the ability to observe the communication will be able to decipher it.
Set the “reject-insecure-requests” property to “true” in the global configuration. While this will allow clients to establish insecure connections to the server, it will reject most requests issued over those connections until the client has used the StartTLS extended operation to convert that connection from an insecure one to one that is secure. However, this option isn’t as good as simply disabling all insecure communication because even though it ensures that clients won’t be permitted to authenticate with an unencrypted bind request, it can’t prevent the client from sending that request in the first place.
Set the “require-secure-authentication” and “require-secure-password-changes” properties to “true” in the password policy configuration. These properties ensure that the server will reject any requests that attempt to authenticate or change passwords that are sent over an unencrypted connection. Like option #2 above, this won’t prevent the requests from being sent, but will merely reject them if they are. But it also won’t protect other sensitive information that may be transferred over the connection.
Use a Strong Password Storage Scheme
When the Directory Server receives a password to store in a user entry, it encodes that password with a password storage scheme. This helps protect that password so that anyone who gains access to the entry (whether over LDAP, in a backup of the database, in an LDIF export, or in some other form) won’t be able to determine what the clear-text password really is. When the server receives a bind request that contains a clear-text password, it will use the password storage scheme and information contained in the encoded password to determine whether the provided clear-text password matches the one used to create the encoded password.
The server offers a number of different password storage scheme options, that fall into different categories:
Some of them, like those that use the UNIX crypt algorithm or versions of the MD5 or SHA-1 digest algorithms, are only intended for legacy purposes like migrating already-encoded passwords from another data store. You definitely shouldn’t use these for new passwords unless you absolutely have to maintain backward compatibility with a legacy system for some period of time.
Some of them, like those that use AES or triple-DES, use reversible encryption to encode the passwords in a way that allows the server to obtain their original clear-text value. These should not be used unless you absolutely have to support a legacy authentication scheme (like CRAM-MD5 or DIGEST-MD5) that requires that the server be able to determine the clear-text representation of the password.
Some of them offer salted variants of more modern digest algorithms, like 256-bit, 384-bit, and 512-bit SHA-2 variants. These schemes are acceptable, especially if you have configured an appropriate set of password validators that require users to have strong passwords, but they are very fast, which means that an attacker can make a lot of guesses in a short period of time.
Some of them use algorithms that are intentionally designed to require a lot of CPU processing or memory access so that they take longer to compute, or so that it’s harder to compute a lot of them at the same time. We currently offer support for the PBKDF2, bcrypt, and scrypt schemes, and plan to add others in the future. These are the strongest options available, and they will definitely have a dramatic impact on how long it will take an attacker to brute-force a password, but they can also dramatically impact the performance of legitimate authentication attempts, and also the performance of an LDIF import that includes clear-text passwords that need to be encoded.
Ideally, you should encode passwords with the strongest scheme that you can tolerate based on your load. If you don’t need more than a few hundred authentications or password changes per second, then you should probably consider the “expensive” schemes to make it as difficult as possible for attackers that may get access to encoded passwords. But if your performance demands are such that you can’t afford enough servers to handle the authentication load with these expensive schemes, then at least use one of the strong modern digests.
Note that if you choose a particular scheme now, or if you have existing passwords encoded with legacy schemes, you aren’t stuck with them, and you don’t have to require all of your users to change their passwords to transition to stronger encodings. For that, we offer the deprecated-password-storage-scheme property in the password policy configuration. If a user has a password encoded with a deprecated scheme, the server will automatically re-encode it using the default scheme the next time they use that password to authenticate.
Require Strong Passwords
It’s important to ensure that passwords are encoded in a secure manner, but it’s even more important that the passwords are strong to start with. If a user has a password that can be easily guessed, then it won’t take long to crack it using even the strongest encoding.
The best practices for choosing secure passwords have changed over the last several years. Things that people used to think were good ideas have turned out to be not so hot. Some of the things that you shouldn’t do are:
Don’t require users to change their passwords on a regular basis for no reason. That’s just annoying to your users and doesn’t improve security in any meaningful way. In fact, it’s more likely to cause people to make bad decisions, like just keeping the same basic password but adding a counter to the end. You should only require users to change their passwords if you suspect that they may have been compromised, or if they’ve been reset by an administrator (e.g., because the user forgot what their previous password was).
Don’t impose a ridiculous upper limit on the length of a password. There’s just no good reason for it. All of the good password storage schemes that we provide generate the same encoded password length regardless of the size of the password being encoded, so you’re not saving any space by preventing long passwords. With all other things being equal, longer passwords are stronger than shorter ones, so you want to encourage people to choose long passwords. It is true that some algorithms may take longer to encode a really long password, so maybe don’t let people choose passwords longer than a few hundred characters, but there’s never a good reason to impose an upper limit of something like ten or twenty characters.
Don’t require passwords to have different classes of characters. It’s entirely possible to have a very strong password that is comprised entirely of lowercase letters, just as it’s entirely possible for a password containing a mix of lowercase and uppercase letters, digits, and symbols to be very weak. You certainly shouldn’t prevent people from using a mix of character types, but you also shouldn’t require it for no good reason.
Don’t impose ridiculously low limits on the number of times the same character may appear consecutively in a password. Long, randomly generated passwords are very strong, and yet it’s entirely possible that such passwords may have the same character appear two or three or four times in a row. It’s very frustrating to choose what is clearly a very strong password only to have it rejected for some stupid reason like this. If you want to prevent passwords comprised of repeated characters, like “aaaaaaaaaa”, then it would probably be better to require them to have a minimum number of unique characters than limiting the number of times the same character may appear in a row.
So what should you do? Despite being a government document, NIST Special Publication 800-63B has some really good advice. And here are some good guidelines that include these and other recommendations:
Don’t allow users to choose obvious or weak passwords. This includes commonly used passwords, dictionary words, and words related to the service that you’re operating. To help with this, the Ping Identity Directory Server offers a dictionary password validator that can reject attempts to use passwords in a given dictionary file, and we offer a couple of instances of that validator preconfigured with dictionary files to use with it: one with over 500,000 of the most commonly used passwords, and one with over 400,000 English words. We recommend that you also configure a validator with your own custom dictionary that includes at least words related to your organization and the products or services you provide., and you may also want to use dictionaries of non-English words. Also, we’ve got plans to provide additional options in this area in the near future.
Impose a minimum length for passwords (but not a maximum). If a password is too short, then it’s too easy to brute force. There are a couple of ways that you can do this in the Ping Identity Directory Server:
You can use the length-based validator to simply impose a minimum length. NIST 800-63B suggests at least eight characters, but to be honest, even a complex eight-character password can be cheaply brute-forced in a handful of hours.
Another option is to use the haystack validator, which uses the concept of password haystacks to evaluate a password’s complexity as a factor of both its length and the types of characters it contains. This is perhaps more complicated to explain to users, but it can do a better job of ensuring resistance to brute force attacks.
Prevent users from choosing passwords that are related to other information that you have about them. For example, you should not allow them to choose a password that matches their username, email address, telephone number, date of birth, etc. The Ping Identity Directory Server offers an attribute value password validator that can be used to ensure that passwords aren’t allowed to match (or optionally contain) the values of other attributes in the entry.
When users are changing their passwords, they should not be permitted to choose a new password that is too similar to their current password. For example, if their current password is “ThisIsMyStrongPassword1”, it’s probably a good idea to prevent them from choosing “ThisIsMyStrongPassword2” as their new password. To achieve this, the Ping Identity Directory Server offers a similarity validator that uses the Levenshtein distance algorithm to compare a proposed new password with the user’s current password (which would have to be provided as part of the password change, since we don’t recommend configuring the server to store passwords in a reversible form) to determine the minimum number of changes (characters added, removed, or replaced).
As noted above, it’s not a good idea to reject passwords just because they have the same password repeated a few times in a row, but it might not be a bad idea to require that they have a minimum number of different characters. The Ping Identity Directory Server offers a unique characters password validator that can accomplish this.
Let the user know what the requirements are. The Ping Identity Directory Server offers a get password quality requirements extended operation that you can use to programmatically retrieve information about the validation that the server will perform, and it offers a password validation details control that you can use to determine which requirements were satisfied and which were not when trying to set a password. I wrote an earlier blog post about using these features.
Recommend the use of a password manager, and recommend using them to generate long random passwords. Certainly don’t do anything that would discourage their use, like prevent users from pasting text into fields on login forms, or interfere with things that might legitimately happen in long random passwords (like having the same character repeated a few times).
If your service imposes additional requirements on password quality that can’t be enforced with the above validators, then I would first recommend taking a hard look at whether they are actually good requirements. Lots of organizations have really dumb rules that either weaken security or at least don’t do anything to improve it while also annoying the end users. But if it turns out that you do have a legitimate need to impose additional types of requirements, then our Server SDK provides an API that allows you to create your own custom password validator implementations.
Require the Current Password for Password Changes
When a user wants to change their password, it’s a good idea to verify that it’s actually them and not someone who has gotten access to their account (e.g., someone using a shared computer that was left logged in). Further, if the user provides their current password when choosing a new password, it allows the server to perform additional types of validation for the new password that may not otherwise be available (e.g., making sure that the new password is not too similar to the current password).
The Ping Identity Directory Server offers a password policy setting to enforce this. If the password-change-requires-current-password property is set to true, then any user changing their own password will be required to provide their current password. This applies to both password changes that use a standard LDAP modify operation and those that use the password modify extended operation. The password modify extended operation already includes a field for the current password, so meeting this requirement for that type of operation is obvious. It’s less obvious for a standard LDAP modify operation, but the way to achieve that is to provide the clear-text representation of the current password in a delete modification, and the desired new password in an add modification, like:
Note that this does not apply to administrative password resets in which one user changes the password for another user.
Enable a Password History
Password reuse is one of the most common ways for accounts to get breached. The biggest risk is when someone uses the same password across multiple sites: if one of those sites is breached and the passwords are obtained, then attackers can try the same credentials on other sites. However, it’s also a bad idea for a user to repeatedly use the same password on the same site.
Repeatedly using the same password on the same site is most commonly an issue if that site requires people to change their password, which, as already stated, is an ill-advised strategy. If you don’t enable password expiration, then people will be less likely to arbitrarily change their passwords, and therefore will be less likely to want to reuse one that they’ve chosen before.
Another common reason for someone wanting to reuse the same password is if they have accidentally locked their account by mis-typing their current password too many times. If this happens, then it’s almost certainly the result of a bad account lockout configuration, which is something that I’ll cover below.
Even if the most common reasons that a user would want to reuse a password are the result of ill-advised configurations, it’s still a good idea to prevent someone from repeating a password that they’ve already had in the past. The server already prevents a user from choosing a new password that is the same as their current password, but if you want to prevent users from repeating passwords they’ve had in the past, then the best way to do that is by enabling a password history. The password policy configuration offers a couple of properties to do this:
password-history-count — Specifies the maximum number of passwords to retain in the history, regardless of how long it’s been since the passwords were in use.
password-history-duration — Specifies the length of time to retain previous passwords in the history, regardless of how many of them have been used during that time.
In either case, the server will maintain an operational attribute with the encoded representations of the user’s former passwords, along with a timestamp indicating when the password was added to the history.
Note that if you do enable a password history, then you may also want to prevent users from changing their passwords too frequently, which you can do with the min-password-age property. This is especially true if you have configured a maximum history count because it’s a common trick for a user who really wants to reuse a previous password to change their password multiple times in quick succession until the password they want to reuse has been flushed from the history. But even though this trick is less effective if you configure a maximum duration rather than a maximum count, it’s still a good idea to prevent frequent password changes in that case too, just to avoid unnecessarily building up a large history.
A relatively short minimum password age, like a day or perhaps even an hour, should be enough of a deterrent to someone who wants to just blow out the password history so that they can reuse a password. Note, however, that the minimum password age only applies to self-changes and not administrative resets. If a user chooses a new password and then immediately forgets it so that they cannot authenticate, then an administrator will be able to reset the password even within the minimum age. And if force-change-on-reset is true, indicating that users are required to choose a new password after an administrative reset, then the minimum age will not interfere with that, either.
Don’t Allow Pre-Encoded Passwords
As previously noted, the server does not store passwords in the clear, but instead encodes all clear-text passwords that it is asked to store (ideally in a strong, non-reversible form). While it is technically possible to send the password to the server in a form that is already encoded, this is generally a very bad idea, for many reasons. Some of them include:
If a password is pre-encoded, the server can’t determine its clear-text representation, and therefore can’t verify that it meets the configured password quality requirements.
Because there are multiple ways of encoding a single password (e.g., using a different salt), there is no way to ensure that the new password isn’t just an alternate encoding for the user’s current password, or for another password in the user’s password history.
The Directory Server generally supports a wide range of applications. If applications pre-encode passwords before sending them to the server, then it makes it more difficult to migrate to a stronger encoding if that becomes necessary or desirable.
The Ping Identity Directory Server offers an allow-pre-encoded-passwords configuration property that controls whether it will accept pre-encoded passwords, and it has a value of false by default. We strongly recommend leaving this as the default.
We do understand that there may be legitimate cases in which it may be necessary to send pre-encoded passwords to the server. For example, if you’re synchronizing data between two sources, and if the data being synchronized includes pre-encoded passwords, then you might not have access to the clear-text password. In that case, rather than reconfiguring the password policy to allow any client to supply passwords in a pre-encoded form, a better alternative is to use the password update behavior request control in any such applications. One of the features that this control offers is a way to indicate that a pre-encoded password should be accepted on a per-change basis. The Ping Identity Synchronization Server (which is included at no additional charge with the Ping Identity Directory Server) makes use of this control for the synchronization that it performs.
Note that the value of the allow-pre-encoded-passwords property does not have any effect on LDIF import. The server will always permit pre-encoded passwords contained in an LDIF file that is loaded into the server with the import-ldif command or with the LDIF import task.
Don’t Allow Multiple Passwords
The two most common attribute types for storing passwords, userPassword (defined in RFC 4519) and authPassword (defined in RFC 3112), are both permitted to have multiple values. In theory, this means that a user could have multiple passwords. However, this is not a good idea. If a user has multiple passwords, then there is no way to control which one is used for any given authentication attempt, so all of them will be considered valid and represents the potential opportunity for the account to be breached.
Further, password policy state is not tied specifically to any password, but rather is maintained on a per-account basis. This means that if a user is allowed to have multiple passwords, then they may be able to exploit that to circumvent certain password policy functionality. For example, if password expiration is enabled (which I’ve already mentioned is a bad idea), then a user with two passwords could just keep changing one of them and continue using the other indefinitely. The same would apply to similar restrictions, like being forced to choose a new password after an administrative reset.
The Ping Identity Directory Server provides an allow-multiple-password-values configuration property to control this behavior, and it has a value of false by default. We do not recommend changing its value to true.
Configure Failure Lockout
If an attacker can get access to the encoded representation of a password, they can throw a lot of hardware at trying to crack it. But if they can’t get access to the encoded representation (and hopefully, that’s a very difficult thing to do), they can still try to crack a password by simply repeatedly trying to log in to an application that authenticates against the server. This is much slower, but it can still be quite effective for users with weak passwords.
You can make this a lot harder by limiting the number of login attempts that someone can make before the account is locked. If an account is locked, then it doesn’t matter what password is tried because any attempt will be rejected. The Ping Identity Directory Server offers support for two types of failure lockout:
Permanent lockout, in which you don’t specify a maximum lockout duration. In this case, the account lockout will remain in effect until an administrator resets the user’s password.
Temporary lockout, in which you do specify a maximum lockout duration (via the lockout-duration configuration property). In this case, the lockout will automatically be lifted after a period of time, but it can still be unlocked earlier by a password reset.
I would strongly recommend using the temporary lockout with a relatively short lockout duration (e.g., one minute). This is sufficient to severely limit the rate at which an attacker can make guesses, but it also ensures that the lockout is short enough that an administrator shouldn’t need to get involved in the case that a user accidentally locks their account but still remembers the correct password. However, I would also strongly recommend setting the lockout failure count (via the lockout-failure-count property) to be high enough that it’s very unlikely to be reached accidentally by merely fat-fingering the password. Ten failed attempts seems like a good value for this purpose.
Note that the Ping Identity Directory Server offers an additional useful feature for helping to prevent accidental failure lockout. If the ignore-duplicate-password-failures property is set to its default value of true, the server will consider repeated attempts to use the same wrong password as just a single failed attempt. This can be helpful in cases where the password has been configured in an application, and that application hasn’t been updated after the user changes their password. If you’re concerned about this scenario, then you may also want to consider enabling password retirement, as described in a later section.
Configure Password Reset Constraints
The account’s owner should be the only one to know its password. If they forget their password and they need to have it reset, there are two basic options:
Have the password reset by a human administrator. In this case, the administrator can choose the password themselves, or they can allow the server to generate it for them (more on this later). Either way, the administrator will end up knowing the password, which means that it should only be usable for the purpose of allowing the user to set a password of their own choosing. The force-change-on-reset configuration property can be used to enable this, and you may also want to set a value for the max-password-reset-age property to limit how long that temporary password is valid.
Create an automated process that allows the user to reset their own password after providing reasonable proof of their identity. To help with this, the Ping Identity Directory Server offers a feature that we call password reset tokens. A password reset token is a single-use password that can be delivered to the user through some out-of-band mechanism (e.g., email message, text message, voice call, mobile push notification, etc.) and can be provided to the password modify extended operation to allow the user to choose a new password. See the DeliverPasswordResetTokenExtendedRequest class in the LDAP SDK for more information about this feature.
Use a Strong Password Generator
The server has the ability to generate passwords under certain circumstances. Some of them include:
When using the password modify extended operation. If the new password field of the request is left empty, the server can generate the new password and return it in the extended response. The password generator used for this purpose is specified using the password-generator property in the password policy configuration.
When using the deliver password reset token extended request, as described in the previous section. The password generator used for this purpose is specified using the password-generator property in the extended operation handler configuration.
We may also introduce additional methods for generating passwords in the future.
When generating a one-time password, password reset token, or single-use token, the time frame for the generated password is inherently very limited (typically a matter of minutes). In such cases, it may be acceptable to have the password be relatively simple. For example, something like eight alphanumeric characters should be sufficient, and you may even feel comfortable with something simpler.
When using the password modify extended operation to perform an administrative reset, the time that a generated password may be valid can be limited by the max-password-reset-age property in the password policy configuration, but there is no such limit for a generated password used for a self-change. In these cases, you may want to ensure that the generated password is substantially stronger. By default, the Ping Identity Directory Server will generate a passphrase that is at least 20 characters long and consists of at least four randomly chosen words. This generated password will hopefully be something that is both memorable and easy to type, and will also serve as an example of the kind of strong passwords that you hope users choose for themselves (although it’s still a better idea to use a password manager in most cases, and to let it generate a strong random password).
Note that the password generator is not guaranteed to generate passwords that will satisfy the configured set of password validators, but the server will accept and use the generated password even if it would have been rejected if the user had chosen it for themselves. If you have eccentric password quality requirements, you may wish to customize the password generator to be more likely to create something that the server would accept.
Consider Using Password Retirement
The Ping Identity Directory Server offers a useful feature called password retirement that allows a user to change their password, but continue using their former password as an alternative to their new password for a limited period of time. This is helpful for cases in which the password might be used in multiple places (especially if it’s configured in an application, and even more especially if there might be multiple instances of that application), because it gives the user the opportunity to update all of the things that use the password without them failing immediately as soon as it is changed. I wrote an earlier blog post about password retirement, so I won’t repeat it here, but it’s definitely something to consider, at least for application accounts.
Consider Using Account Status Notifications
Another potentially useful password policy feature that the Ping Identity Directory Server offers is account status notifications. This allows the server to perform custom processing whenever certain events occur that affect user accounts, like a user’s account has been locked as a result of too many failed attempts, an authentication attempt has failed because the account is expired or has been unused for too long, a user’s password is changed or reset by an administrator, etc.
The server includes support for a couple of different types of account status notification handlers out of the box: one that is capable of sending an email message to the end user and/or to administrators when such an event occurs, and one that simply logs a message about the event. Our Server SDK also provides support for creating custom account status notification handlers, so you can integrate with other systems that you might use in your environment. We’re also going to be substantially improving our account status notification handler subsystem in the near future.
One purpose of account status notification handlers is to provide a means of letting end users know about substantial events that affect their accounts. This is useful from a security perspective because if a user sees something that indicates something may be amiss, then they can inquire about it. But account status notification handlers can also serve as a kind of auditing mechanism for these kinds of events so that administrators are made aware of things that might suggest a problem or an attack. For example, if a large number of accounts are being locked out, or if the same account is repeatedly being locked out, then that suggests someone might be trying a password guessing attack.
Alternatives to Arbitrary Password Expiration
I’ve already pointed out on multiple occasions that arbitrary password expiration is not recommended. However, there may be reasons that you want users to change their passwords that might not be simply the result of them having the same password for too long.
For example, if you believe that one or more user accounts might have had their passwords exposed (whether in the clear or in encoded form), then it’s a very good idea to require them to choose a new password. The Ping Identity Directory Server offers a couple of features to help with this:
The password policy offers a require-change-by-time configuration property that allows you to require all users associated with that policy to change their passwords by a specified time. Failure to comply will cause their account to be locked until the password is reset by an administrator.
The password policy state extended operation provides a mechanism for manipulating the account state for a user or set of users. Using this extended operation, or the manage-account tool that provides a simple command-line interface to the operation, you could put a specified account or set of accounts in a “must change password” state that will require them to change their passwords the next time they authenticate. See my previous blog post about managing password policy state for more information.
If you’re considering password expiration as a means of ensuring that users will be required to authenticate every so often or their accounts will be locked, then we offer a better alternative to that: idle account lockout. If you update the password policy to enable last login time tracking (via the last-login-time-attribute and last-login-time-format configuration properties), then the server will maintain a record of the last time that each user successfully authenticated. If you also set a value for the idle-lockout-interval property, then a user who hasn’t authenticated in at least that length of time will be locked out of their account until the password is reset by an administrator.
If the reason for forcing a password change is because you want to upgrade the password storage scheme that you’re using, you can do that without actually requiring a password change. As noted above in the section on password storage schemes, you can simply make the desired scheme the new default and mark the old scheme as deprecated. The next time a user authenticates with a password encoded with the deprecated scheme, it will be automatically re-encoded using the new default scheme.
If you have other reasons that you were considering password expiration that aren’t covered by these options, then let us know what they are, and we’ll let you know whether there might be a suitable alternative.
Other Related Settings Outside the Password Policy
There are a few other related settings that you might want to consider setting, even though they’re not strictly part of the password policy configuration. They include:
You should enable data encryption in the server so that data is not stored in the clear in the database. The best way to do this is to enable encryption when setting up the server, but if you need to do it after the fact, you can use the encryption-settings tool to manage the set of encryption settings definitions that are available in the server, then update the values of the the encrypt-data, encryption-settings-cipher-stream-provider, encrypt-backups-by-default, and encrypt-ldif-exports-by-default global configuration properties. Enabling encryption can be done on the fly, and any subsequent writes will cause the target entry to be encrypted, but you may still want to export the data to LDIF and re-import to ensure that all the existing data gets encrypted.
You may wish to configure the server to delay the response to a failed bind operation by a specified length of time (e.g., maybe a second). This can help slow down online password guessing attacks, and it can be used either in conjunction with or as an alternative to locking an account after too many failed attempts. This setting can be configured through the failed-bind-response-delay property in the LDAP connection handler configuration.
You may want to configure the userPassword and authPassword attributes as sensitive attributes within the server, and ensure that they can never be retrieved over LDAP, even in encoded form, and even by root users. Check out my earlier blog post about sensitive attributes for more information on this subject.
Consider enabling one or more two-factor authentication mechanisms. While it’s still important to ensure that users have strong passwords, two-factor authentication adds yet another layer of protection that an attacker must overcome even if they do happen to learn a user’s password. I also wrote an earlier blog post about this topic.