PingDS 8.0.0

Passwords and accounts

Examples in this documentation depend on features activated in the ds-evaluation setup profile.

The code samples demonstrate how to contact the server over HTTPS using the deployment CA certificate. Before trying the samples, generate the CA certificate in PEM format from the server deployment ID and password:

$ dskeymgr \
 export-ca-cert \
 --deploymentId $DEPLOYMENT_ID \
 --deploymentIdPassword password \
 --outputFile ca-cert.pem

The ldappasswordmodify command lets authorized users change their own passwords and reset other users' passwords.

Reset a password

Whenever one user changes another user’s password, DS servers consider it a password reset. Often password policies specify that users must change their passwords again after a password reset.

Assume password administrator Kirsten Vaughan has the password-reset privilege. The following example shows Kirsten resetting Andy Hall’s password:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
 --bindPassword bribery \
 --authzID "dn:uid=ahall,ou=people,dc=example,dc=com"
Show output
The LDAP password modify operation was successful
Generated Password:  <password>
More information

If a client application performs the LDAP password modify extended operation on a connection that is bound to a user (in other words, when a user first does a bind on the connection, then requests the LDAP Password Modify extended operation), then the operation is performed as the user associated with the connection. If the user associated with the connection is not the same user whose password is being changed, then DS servers consider it a password reset.

To change, rather than reset, the password as the user while binding as an application or an administrator, use the LDAP Password Modify extended operation with an authorization ID. Alternatively, use proxied authorization, as described in Proxied authorization.

If you reset a password, and do not want it to count as a password reset, use the manage-account command with the set-password-is-reset hidden option, supported only for testing:

$ manage-account \
 set-password-is-reset \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --targetDN uid=ahall,ou=people,dc=example,dc=com \
 --operationValue true \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin

Change your password

Users can change their own passwords with the ldappasswordmodify command as long as they know their current password:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN "uid=ahunter,ou=people,dc=example,dc=com" \
 --bindPassword egregious \
 --newPassword chngthspwd

The same operation works for directory superusers, such as uid=admin:

$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --authzID dn:uid=admin \
 --currentPassword password \
 --newPassword OzNOkkfkTJDSW9Bg

Check password quality

The ldappasswordmodify and ldapmodify commands support password quality advice controls to get additional information about why a password update failed. When you use the request control and a password update fails, the server can send the response control with details indicating which validators rejected the new password.

You can use this as a means to test a password, and to evaluate the effectiveness of a new password policy.

The new LDAP control has interface stability: Evolving.

The following commands demonstrate how the tools show the information from the response control:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: dc=example,dc=com
changetype: modify
add: aci
aci: (targetcontrol="PasswordQualityAdvice") (version 3.0; acl
  "Authenticated users can check password quality";
  allow(read) userdn="ldap:///all";)
EOF
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=admin \
 --bindPassword password << EOF
dn: cn=Minimum length policy,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: ds-pwp-password-policy
objectClass: ds-pwp-validator
objectClass: ds-pwp-length-based-validator
cn: Minimum length policy
ds-pwp-password-attribute: userPassword
ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA512
ds-pwp-length-based-min-password-length: 8
subtreeSpecification: {base "ou=people", specificationFilter "(uid=pshelton)" }
EOF
$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=pshelton,ou=People,dc=example,dc=com \
 --bindPassword nosedive \
 --control PasswordQualityAdvice:true \
 --control NoOp \
 --newPassword passwd
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 is shorter than the minimum required length of 8 characters

The new password was rejected by the password policy located in "cn=Minimum length policy,dc=example,dc=com"

The following password quality criteria were not satisfied:
* length-based with parameters {max-password-length=0, min-password-length=8}

Notice that the check can be performed as a no-op.

Passwords with special characters

DS servers expect passwords to be UTF-8 encoded and base64-encoded when included in LDIF. UTF-8 characters such as à or ô must be correctly encoded:

$ export LANG=en_US.UTF-8
$ ldappasswordmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=wlutz,ou=People,dc=example,dc=com \
 --bindPassword bassinet \
 --newPassword pàsswȏrd
$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=wlutz,ou=People,dc=example,dc=com \
 --bindPassword pàsswȏrd \
 --baseDN dc=example,dc=com \
 "(uid=wlutz)" \
 1.1
Show output
dn: uid=wlutz,ou=People,dc=example,dc=com

Read password policy state

DS servers have a password policy state virtual attribute enabled by default. It provides information similar to the manage-account get-all command.

Accounts with access to read the operational attribute ds-pwp-state-json get information from the following fields. Many of the fields only appear when the situation requires:

Field Description

account-expiration-time

Expiration time

account-is-disabled

Boolean

account-is-expired

Boolean

account-is-idle-locked

Boolean

account-is-reset-locked

Boolean, true if the password was not changed soon enough after reset

account-is-usable

Boolean

authentication-failure-times

Authentication failure times

current-authentication-failure-count

Number of recorded authentication failures

expire-passwords-without-warning

Boolean

failure-lockout-count

Maximum number of authentication failures allowed before lockout

failure-lockout-expiration-interval

Duration in seconds of account lockout after too many authentication failures

force-change-on-add

Boolean, true when the password must change immediately after DS adds the account

force-change-on-reset

Boolean, true when the password must change after another user resets it

grace-login-use-times

Grace login times

idle-lockout-interval-seconds

Maximum seconds an account can remain idle (no recent authentications) before lockout

idle-lockout-time

Time account locks for being idle (no recent authentications)

idle-lockout

Seconds until the account locks for being idle

is-within-minimum-password-age

Boolean, whether the password is too new to change

last-login-time

Time of the last successful authentication

max-password-reset-age-seconds

Maximum seconds to change the password after reset

maximum-grace-login-count

Number of grace logins allowed after expiration to set a new password

maximum-password-age-seconds

Maximum seconds the password can remain the same

maximum-password-history-count

Maximum number of records allowed in the account’s list of old password

maximum-password-history-duration-seconds

Maximum number of seconds DS retains old passwords

minimum-password-age-expiration-time

Time the password is old enough to change

minimum-password-age-seconds

Minimum seconds between password changes

must-change-password

Boolean, true when the password must change as the next action on the account

password-change-time

Time the password changed

password-expiration-time

Time the password expires

password-expiration-warning-interval-seconds

Seconds before bind responses include expiry notifications

password-expiration-warning-issued

Boolean, true if DS has returned a notification about expiry

password-expiration-warning-time

Time DS first returned a notification about expiry

password-expiration-warning

Seconds ago DS first returned a notification about expiry

password-expiration

Seconds until the password expires

password-is-expired

Boolean

password-policy-dn

The password policy governing the current account

recent-login-history

Array, times of the last successful authentications

remaining-authentication-failure-count

Number, difference between the maximum and current authentication failures

remaining-grace-login-count

Number, difference between the maximum and used grace login count

require-secure-authentication

Boolean, true when authentication must prevent exposing the credentials

require-secure-password-changes

Boolean, true when password changes must prevent exposing the credentials

reset-lockout-time

Time the account locks after reset unless the password changes

seconds-remaining-in-failure-lockout

Number of seconds before the locked account unlocks

seconds-remaining-in-minimum-password-age

Seconds until the password is old enough to change

seconds-since-account-expiration

Seconds since the account expired

seconds-since-idle-lockout

Seconds since the account locked for being idle (no recent authentications)

seconds-since-last-login

Seconds since the last successful authentication

seconds-since-password-change

Seconds since the password changed

seconds-since-password-expiration-warning

Seconds since DS sent the first bind response with an expiry notification

seconds-since-password-expiration

Seconds since the password expired

seconds-until-account-expiration

Seconds until the account expires

seconds-until-idle-lockout

Seconds until the account locks for being idle (no recent authentications)

seconds-until-password-expiration-warning

Seconds until DS starts sending bind responses with expiry notifications

seconds-until-password-expiration

Seconds until the password expires

seconds-until-reset-lockout

Seconds until the account locks after reset unless the password changes

used-grace-login-count

Number of recorded grace logins

To read the attribute:

  1. Make sure the reader has access:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: dc=example,dc=com
    changetype: modify
    add: aci
    aci: (targetattr="ds-pwp-state-json")(version 3.0;
      acl "Read pwp state"; allow (read,search,compare)
      userdn="ldap:///uid=kvaughan,ou=people,dc=example,dc=com";)
    EOF
  2. Read the attribute on an account:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)" \
     ds-pwp-state-json
    Show output
    dn: uid=bjensen,ou=People,dc=example,dc=com
    ds-pwp-state-json: { "require-secure-authentication": true, "password-policy-dn": "cn=Default Password Policy,cn=Password Policies,cn=config", "force-change-on-reset": false, "account-is-expired": false, "account-is-idle-locked": false, "account-is-disabled": false, "account-is-reset-locked": false, "must-change-password": false, "password-is-expired": false, "is-within-minimum-password-age": false, "account-is-usable": true, "require-secure-password-changes": true, "force-change-on-add": false }

Check account usability

The account usability control lets a password administrator read information about whether the user can authenticate to the directory:

  • The remote LDAP directory service must support the LDAP control, which has OID 1.3.6.1.4.1.42.2.27.9.5.8.

  • The password administrator must be able to use the LDAP control.

To try the account usability control:

  1. Enable the password administrator to use the LDAP account usability control.

    The following example sets a global ACI for Kirsten Vaughan:

    $ dsconfig \
     set-access-control-handler-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --add global-aci:"(targetcontrol=\"AccountUsability\")\
     (version 3.0; acl \"Account usability access\"; allow(read) \
     userdn=\"ldap:///uid=kvaughan,ou=People,dc=example,dc=com\";)" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
  2. Use a password policy that produces results for account usability, as in the following example:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: cn=Lockout with max age and grace logins,dc=example,dc=com
    objectClass: top
    objectClass: subentry
    objectClass: ds-pwp-password-policy
    cn: Lockout with max age and grace logins
    ds-pwp-password-attribute: userPassword
    ds-pwp-default-password-storage-scheme: PBKDF2-HMAC-SHA256
    ds-pwp-lockout-failure-expiration-interval: 10 m
    ds-pwp-grace-login-count: 3
    ds-pwp-lockout-duration: 5 m
    ds-pwp-lockout-failure-count: 3
    ds-pwp-max-password-age: 30 d
    subtreeSpecification: { base "ou=people", specificationFilter "(uid=bjensen)" }
    EOF
  3. Use the account usability control to get information about an account:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     --control AccountUsability:true \
     "(uid=bjensen)" \
     1.1
    Show output
    # Account Usability Response Control
    # The account is usable
    # Time until password expiration:  <time>
    dn: uid=bjensen,ou=People,dc=example,dc=com
  4. Perform actions to change the account usability information on the account:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=bjensen,ou=people,dc=example,dc=com \
     --bindPassword wrong-password \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)" \
     1.1
    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=bjensen,ou=people,dc=example,dc=com \
     --bindPassword wrong-password \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)" \
     1.1
    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=bjensen,ou=people,dc=example,dc=com \
     --bindPassword wrong-password \
     --baseDN dc=example,dc=com \
     "(uid=bjensen)" \
     1.1
  5. Use the account usability control again to get the changes:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     --control AccountUsability:true \
     "(uid=bjensen)" \
     1.1
    Show output
    # Account Usability Response Control
    # The account is not usable
    # The account is locked
    # Time until the account is unlocked:  <time>