---
title: Configure password policies
description: Make sure you keep per-server password policy settings aligned across replicated DS servers. When per-server password policy settings differ between replicas, the results can be surprising to end users.
component: pingds
version: 8.1
page_id: pingds:security-guide:pwp-configure
canonical_url: https://docs.pingidentity.com/pingds/8.1/security-guide/pwp-configure.html
revdate: 2025-10-22T14:42:39Z
keywords: ["Features", "LDAP", "Security", "Setup &amp; Configuration"]
section_ids:
  default-pwp: Adjust the default password policy
  recommended-pwp: Configure a NIST-inspired subentry policy
  create-per-server-pwp: Create a per-server password policy
---

# Configure password policies

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Make sure you keep per-server password policy settings aligned across replicated DS servers. When per-server password policy settings differ between replicas, the results can be surprising to end users.As an example, suppose the user's password policy depends on a password storage scheme enabled on the replica where the user changes their password and disabled on the replica where they later authenticate:- The user changes their password on the first replica.

  The password update succeeds.

  Replication replays the change.

- The user authenticates on the second replica.

  Authentication fails even though the second replica has the correct password hash. The password storage scheme is disabled in the local per-server configuration. |

## Adjust the default password policy

You can reconfigure the default password policy, for example, to check that passwords do not contain complete attribute values, and to prevent password reuse. The default policy is a per-server password policy.

1. Apply the changes to the default password policy:

   ```console
   $ dsconfig \
    set-password-policy-prop \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --policy-name "Default Password Policy" \
    --set password-history-count:7 \
    --set password-validator:Attribute\ Value \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

2. Check your work:

   ```console
   $ dsconfig \
    get-password-policy-prop \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --policy-name "Default Password Policy" \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

   > **Collapse: Show output**
   >
   > ```
   > Property                                  : Value(s)
   > ------------------------------------------:--------------------------
   > account-status-notification-handler       : -
   > allow-expired-password-changes            : false
   > allow-user-password-changes               : true
   > default-password-storage-scheme           : PBKDF2-HMAC-SHA256
   > deprecated-password-storage-scheme        : -
   > expire-passwords-without-warning          : false
   > force-change-on-add                       : false
   > force-change-on-reset                     : false
   > grace-login-count                         : 0
   > idle-lockout-interval                     : 0 s
   > last-login-time-attribute                 : -
   > last-login-time-format                    : -
   > lockout-duration                          : 0 s
   > lockout-failure-count                     : 0
   > lockout-failure-expiration-interval       : 0 s
   > max-password-age                          : 0 s
   > max-password-reset-age                    : 0 s
   > min-password-age                          : 0 s
   > password-attribute                        : userPassword
   > password-change-requires-current-password : false
   > password-expiration-warning-interval      : 5 d
   > password-generator                        : Random Password Generator
   > password-history-count                    : 7
   > password-history-duration                 : 0 s
   > password-validator                        : Attribute Value
   > previous-last-login-time-format           : -
   > require-change-by-time                    : -
   > require-secure-authentication             : true
   > require-secure-password-changes           : true
   > ```

3. Test changes to the default password policy.

   For example, the following tests demonstrate the attribute value password validator. The attribute value password validator rejects a new password when the password is contained in attribute values on the user's entry.

   By default, the attribute value password validator checks all attributes, checks whether portions of the password string match attribute values, where the portions are strings of length 5, and checks the reverse of the password as well:

   ```console
   $ dsconfig \
    get-password-validator-prop \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --validator-name Attribute\ Value \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

   > **Collapse: Show output**
   >
   > ```
   > Property               : Value(s)
   > -----------------------:--------------------------------------------------
   > check-substrings       : true
   > enabled                : true
   > match-attribute        : All attributes in the user entry will be checked.
   > min-substring-length   : 5
   > test-reversed-password : true
   > ```

   Consider the attributes present on Babs Jensen's entry:

   ```console
   $ ldapsearch \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN uid=bjensen,ou=People,dc=example,dc=com \
    --bindPassword hifalutin \
    --baseDN dc=example,dc=com \
    "(uid=bjensen)"
   ```

   > **Collapse: Show output**
   >
   > ```
   > dn: uid=bjensen,ou=People,dc=example,dc=com
   > objectClass: person
   > objectClass: cos
   > objectClass: oauth2TokenObject
   > objectClass: inetOrgPerson
   > objectClass: organizationalPerson
   > objectClass: posixAccount
   > objectClass: top
   > classOfService: bronze
   > cn: Barbara Jensen
   > cn: Babs Jensen
   > departmentNumber: 3001
   > description: Original description
   > diskQuota: 10 GB
   > facsimileTelephoneNumber: +1 408 555 1992
   > gidNumber: 1000
   > givenName: Barbara
   > homeDirectory: /home/bjensen
   > l: San Francisco
   > mail: bjensen@example.com
   > mailQuota: 1 GB
   > manager: uid=trigden, ou=People, dc=example,dc=com
   > oauth2Token: {"access_token":"123","expires_in":59,"token_type":"Bearer","refresh_token":"456"}
   > ou: Product Development
   > ou: People
   > preferredLanguage: en, ko;q=0.8
   > roomNumber: 0209
   > sn: Jensen
   > street: 201 Mission Street Suite 2900
   > telephoneNumber: +1 408 555 1862
   > uid: bjensen
   > uidNumber: 1076
   > ```

   Using the attribute value password validator, passwords like `bjensen12` and `babsjensenspwd` are not valid because substrings of the password match complete attribute values:

   ```console
   $ ldappasswordmodify \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
    --bindPassword hifalutin \
    --newPassword bjensen12
   ```

   > **Collapse: Show output**
   >
   > ```
   > The LDAP password modify operation failed: 19 (Constraint Violation)
   > Additional Information:  The provided new password failed the validation checks defined in the server: The provided
   > password was found in another attribute in the user entry
   > ```

   ```console
   $ ldappasswordmodify \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
    --bindPassword hifalutin \
    --newPassword babsjensenspwd
   ```

   > **Collapse: Show output**
   >
   > ```
   > The LDAP password modify operation failed: 19 (Constraint Violation)
   > Additional Information:  The provided new password failed the validation checks defined in the server: The provided
   > password was found in another attribute in the user entry
   > ```

## Configure a NIST-inspired subentry policy

You can configure a password policy inspired by NIST 800-63 requirements:

* Use a strong password storage scheme.

* Enforce a minimum password length of 8 characters.

* Check for matches in a dictionary of compromised passwords.

* Do not use composition rules for password validation.

  In other words, do not require a mix of special characters, upper and lower case letters, numbers, or other composition rules.

* Do not enforce arbitrary password changes.

  In other words, do not set a maximum password age.

Follow these steps to set up a replicated, NIST-inspired LDAP subentry password policy:

1. Gzip a copy of a text file of common compromised passwords, one word per line.

   This example shows the gzipped text file as `/tmp/10k_most_common.gz`. After successfully updating a subentry password policy with the dictionary data, the input file is no longer required. Lists of common passwords can be found online.

2. Make sure you have enabled a strong storage scheme.

   Creating a password storage scheme requires access to edit the server configuration, which you might not have when creating a subentry password policy. This example therefore uses the `PBKDF2-HMAC-SHA512` storage scheme, which is enabled by default to use 10,000 iterations.

   *This scheme is intentionally much slower and more CPU-intensive* than the `PBKDF2-HMAC-SHA256` scheme with 10 iterations used by the default password policy when you install DS. Test that you have enough resources to sustain the expected peak rates of impacted operations before using a much stronger password storage scheme in your production deployment.

   Impacted operations include:

   * Adding or importing entries with passwords.

   * Authenticating using a password, such as simple bind.

   * Updating or resetting a password.

3. Make sure password policy administrators have the `subentry-write` privilege, and any required ACIs *(tooltip: \<div class="paragraph">
   \<p>An instruction or rule that can be used to grant or deny access to users to perform operations on a server.\</p>
   \</div>)* needed to write password policy subentries in the directory data.

   The following example grants access to password administrators. The administrator accounts are in the data where the password policy is to be stored:

   ```console
   $ ldapmodify \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN uid=admin \
    --bindPassword password << EOF
   dn: cn=subentry-write privilege for administrators,dc=example,dc=com
   objectClass: collectiveAttributeSubentry
   objectClass: extensibleObject
   objectClass: subentry
   objectClass: top
   cn: subentry-write privilege for administrators
   ds-privilege-name;collective: subentry-write
   subtreeSpecification: {base "ou=people", specificationFilter
     "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)" }

   dn: dc=example,dc=com
   changetype: modify
   add: aci
   aci: (target="ldap:///dc=example,dc=com")
    (targetattr = "*||ds-pwp-password-policy-dn||pwdPolicySubentry||subtreeSpecification")
    (version 3.0; acl "Admins can manage entries and password policies"; allow(all)
    groupdn = "ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";)
   EOF
   ```

   Notice here that the directory superuser, `uid=admin`, assigns privileges. Any administrator with the `privilege-change` privilege can assign privileges. However, if the administrator can update administrator privileges, they can assign themselves the `bypass-acl` privilege. Then they are no longer bound by access control instructions, including both user data ACIs and global ACIs. For this reason, do not assign the `privilege-change` privilege to normal administrator users.

4. Create the password policy as one of the password policy administrators:

   ```console
   $ ldapmodify \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
    --bindPassword bribery << EOF
   dn: cn=NIST inspired policy,dc=example,dc=com
   objectClass: top
   objectClass: subentry
   objectClass: ds-pwp-password-policy
   objectClass: ds-pwp-validator
   objectClass: ds-pwp-length-based-validator
   objectClass: ds-pwp-dictionary-validator
   cn: NIST inspired policy
   ds-pwp-password-attribute: userPassword
   ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA512
   ds-pwp-length-based-min-password-length: 8
   ds-pwp-dictionary-data:<file:///tmp/10k_most_common.gz
   subtreeSpecification: {base "ou=people", specificationFilter "(objectclass=person)" }
   EOF
   ```

   After successfully adding the policy with the dictionary data, you can delete the input file.

5. Check the password policy works appropriately.

   The following example shows a rejected password modification:

   ```console
   $ ldappasswordmodify \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
    --bindPassword hifalutin \
    --newPassword secret12
   ```

   > **Collapse: Show output**
   >
   > ```
   > The LDAP password modify operation failed: 19 (Constraint Violation)
   > Additional Information:  The provided new password failed the validation checks defined in the server: The provided
   > password was found in another attribute in the user entry
   > ```

   The following example shows an accepted password modification:

   ```console
   $ ldappasswordmodify \
    --hostname localhost \
    --port 1636 \
    --useSsl \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --bindDN "uid=bjensen,ou=people,dc=example,dc=com" \
    --bindPassword hifalutin \
    --newPassword aET1OjQeVJECSMgxDPs3U6In
   ```

   > **Collapse: Show output**
   >
   > ```
   > The LDAP password modify operation was successful
   > ```

## Create a per-server password policy

This example adds a per-server password policy for new users who have not yet used their credentials to bind:

1. Create the new password policy:

   ```console
   $ dsconfig \
    create-password-policy \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --policy-name "New Account Password Policy" \
    --set default-password-storage-scheme:PBKDF2-HMAC-SHA256 \
    --set force-change-on-add:true \
    --set password-attribute:userPassword \
    --type password-policy \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

   As per-server password policies are not replicated, repeat this step on all replica directory servers.

2. Check your work:

   ```console
   $ dsconfig \
    get-password-policy-prop \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --policy-name "New Account Password Policy" \
    --trustStorePath /path/to/opendj/config/keystore \
    --trustStoreType PKCS12 \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

   > **Collapse: Show output**
   >
   > ```
   > Property                                  : Value(s)
   > ------------------------------------------:-------------------
   > account-status-notification-handler       : -
   > allow-expired-password-changes            : false
   > allow-user-password-changes               : true
   > default-password-storage-scheme           : PBKDF2-HMAC-SHA256
   > deprecated-password-storage-scheme        : -
   > expire-passwords-without-warning          : false
   > force-change-on-add                       : true
   > force-change-on-reset                     : false
   > grace-login-count                         : 0
   > idle-lockout-interval                     : 0 s
   > last-login-time-attribute                 : -
   > last-login-time-format                    : -
   > lockout-duration                          : 0 s
   > lockout-failure-count                     : 0
   > lockout-failure-expiration-interval       : 0 s
   > max-password-age                          : 0 s
   > max-password-reset-age                    : 0 s
   > min-password-age                          : 0 s
   > password-attribute                        : userPassword
   > password-change-requires-current-password : false
   > password-expiration-warning-interval      : 5 d
   > password-generator                        : -
   > password-history-count                    : 0
   > password-history-duration                 : 0 s
   > password-validator                        : -
   > previous-last-login-time-format           : -
   > require-change-by-time                    : -
   > require-secure-authentication             : false
   > require-secure-password-changes           : false
   > ```

3. Change the user's password policy after the password is successfully updated.

   For instructions on assigning a per-server password policy, refer to [Assign a password policy to a user](pwp-assign.html#assign-pwp-to-individual).
