Managing Password Policy State in the Ping Identity Directory Server

The Ping Identity Directory Server offers a wealth of password policy functionality, and a lot of them require maintaining some kind of state information in the user’s entry. This includes things like:

  • The password policy by which the user is governed
  • The encoded passwords for the user
  • Whether the user’s account has been administratively disabled
  • When the user’s account will become active or will be deactivated
  • When the user’s password was last changed
  • When the user was first warned about an upcoming password expiration
  • Whether the user will be forced to change their password before being allowed to perform any other operations
  • A history of previous passwords for the user
  • Information about recent failed authentication attempts
  • Information about any grace logins used
  • The time the user last authenticated
  • The address of the client from which the user last authenticated
  • A retired password for the user

It’s often the case that an administrator application may want to obtain information about a user’s password policy state or to alter that state in some way. In this post, I’ll describe some of the options that the Ping Identity Directory Server provides to accomplish this.

Direct Manipulation of Operational Attributes

The password policy state for a user is maintained with operational attributes in the user’s entry, operating in conjunction with the password policy that governs that user. As such, you’d think that just altering the values of these attributes would be the best way to alter a user’s password policy state.

That is true for some of these password policy state attributes. The following attributes are supported for direct manipulation by applications and administrators:

  • ds-pwp-password-policy-dn — Specifies the DN of the configuration entry for the password policy that governs the user. If this is not specified, the user will be governed by the server’s default password policy. If it specifies the DN of an entry that does not exist or is not a password policy, then the user will not be permitted to authenticate.
  • ds-pwp-account-disabled — Indicates whether the user’s account is administratively disabled. If the attribute exists and has a value of TRUE, then the user account will be disabled and unable to authenticate. If the attribute is missing or has a value of FALSE, then the user account will not be considered disabled.
  • ds-pwp-account-expiration-time — Specifies a date and time (in generalized time format) that the user account will be considered expired and no longer able to authenticate. If this is not specified, the account will not expire. Note that account expiration is not the same as password expiration; account expiration is used for temporary accounts (e.g., for a contractor), whereas password expiration is used to require users to periodically change their passwords.
  • ds-pwp-account-activation-time — Specifies a date and time (in generalized time format) that the user account will become active. If this is specified, then the user will not be permitted to authenticate until after this time.

However, other operational attributes used to maintain password policy state are not directly writable by applications or administrator. These attribute type definitions are marked with the NO-USER-MODIFICATION constraint in the schema and are not considered part of the public interface that we expose. We may change the value format for these attributes, or even the attribute types, between releases without any prior warning. If you need to alter the password policy state in some other way, then you’ll need to use a different approach.

Resetting the User’s Password

There are several reasons that a user may not be allowed to authenticate. Some of them are directly controllable by an administrator using the operational attributes specified above. However, there are a number of other conditions that are not as directly controllable by administrators. These include:

  • The user’s password is expired
  • The user’s account has been locked because of too many failed authentication attempts
  • The user’s account has been locked because it has been too long since they last authenticated
  • The user’s account has been locked because they did not choose a new password soon enough after an administrative reset

Each of these conditions can be resolved by simply resetting the user’s password. Once the password has been reset, the account should immediately become usable.

Note that if the password is expired but the user still knows the right value, and if the allow-expired-password-changes property is set to true in the password policy that governs the user, then the user could change their own password using the password modify extended operation. This would presumably happen over an unauthenticated connection, but where the request includes the current password for the target user so it will be authorized as that user.

Also note that if the user’s account is only temporarily locked as a result of too many failed authentication attempts, then the user could just wait out the lockout specified by the lockout-duration property in the password policy. If they provide the correct password after the lockout duration has elapsed, they should be permitted to authenticate.

The Password Policy State Extended Operation

The password policy state extended operation is the Swiss Army knife of password policy state management in the Ping Identity Directory Server. Unlike the attributes that are used to actually store the information, this extended operation does provide a documented, stable, and supported interface for low-level manipulation of a user’s password policy state.

If you’re using the UnboundID LDAP SDK for Java, you can access this operation through the PasswordPolicyStateExtendedRequest, PasswordPolicyStateExtendedResult, and PasswordPolicyStateOperation classes, and the Javadoc for the request class has an example that demonstrates its use. If you’re using another API, then the Javadoc for the request class is still useful because it describes the OID and the value encoding for the operation.

Things that you can do with the password policy state extended operation include:

  • Retrieve the DN of the password policy that governs an account
  • Get, set, and clear the disabled state for an account
  • Get, set, and clear an account’s expiration time
  • Retrieve the length of time in seconds until an account will expire
  • Determine whether an account is expired
  • Get, set, and clear an account’s activation time
  • Retrieve the length of time in seconds until an account will become active
  • Determine whether an account is not yet active
  • Get, set, and clear the time that an account’s password was last changed
  • Determine whether an account’s password is currently expired
  • Retrieve the time that an account’s password will expire
  • Retrieve the length of time in seconds until an account’s password will expire
  • Retrieve the length of time in seconds until the account will be eligible to receive a warning about an upcoming password expiration
  • Get, set, and clear the time that an account was first warned about an upcoming password expiration
  • Get and set an account’s failure lockout state
  • Retrieve the time that an account was locked because of too many authentication failures
  • Get, update, set, and clear the set of authentication failure times for an account
  • Retrieve the length of time in seconds until a temporarily failure-locked account will be unlocked
  • Retrieve the number of failed authentication attempts until an account will be locked
  • Get, set, and clear an account’s last login time
  • Get, set, and clear an account’s last login IP address
  • Determine whether an account is currently locked because it has been too long since it last authenticated
  • Get the time that an account will be locked because it has been too long since it last authenticated
  • Retrieve the length of time in seconds until an account will be locked because it has been too long since it last authenticated
  • Get, set, and clear the “must change password” state for an account
  • Determine whether an account is currently locked because they failed to change their password in a timely manner after an administrative reset
  • Retrieve the time that an account was locked because they failed to change their password in a timely manner after an administrative reset
  • Retrieve the length of time in seconds until an account will be locked because they failed to change their password in a timely manner after an administrative reset
  • Get, update, set, and clear the set of grace login use times for an account
  • Retrieve the number of remaining grace logins for an account
  • Get, set, and clear the most recent “require change by time” value with which an account has complied
  • Retrieve the length of time in seconds that an account has to comply with a “require change by time” constraint in the password policy
  • Get the number of passwords in an account’s password history
  • Clear an account’s password history
  • Indicate whether an account has a retired password
  • Retrieve the time that an account’s former password was retired
  • Retrieve the time that an account’s retired password will stop being valid
  • Purge an account’s retired password
  • Retrieve a set of account usability errors, warnings, and notices
  • Determine whether an account is usable
  • Retrieves the set of SASL mechanisms that an account may use to authenticate
  • Retrieves the set of OTP delivery mechanisms that are available for an account
  • Determine whether an account has at least one TOTP shared secret
  • Add, remove, set, and clear the set of TOTP shared secrets for an account
  • Determine whether an account has at least one YubiKey OTP device registered
  • Get, update, set, and clear the public IDs of any YubiKey OTP devices that have been registered for an account
  • Determine whether an account has a static password set

The manage-account Command-Line Tool

While the password policy state extended operation is very powerful and flexible, you kind of need to write code to be able to use it. That’s fine if you’re writing an application that needs to be able to do this kind of thing, but not so much if you’re an administrator that just needs to update a user account. Fortunately, we offer a manage-account tool that gives you all of the functionality of the password policy state extended operation in a simple command-line utility.

This tool uses subcommands to indicate which password policy state functionality you want to invoke. The --helpSubcommands argument can be used to obtain a list of all of the available subcommands, but many of them are of the form “get-{property}”, “set-{property}”, or “clear-{property}”, like “get-account-is-disabled”, “set-account-is-disabled”, or “clear-account-is-disabled”. There’s also a “get-all” subcommand that displays the values of all password policy state attributes for a user.

The manage-account tool can operate on one or more entries, specifying them by DN (using the --targetDN or --dnInputFile arguments), by user ID (via the --targetUserID or --userIDInputFile arguments), or by an arbitrary filter (using the --targetFilter and --filterInputFile arguments). It can use multiple threads to process changes to multiple entries concurrently.

For example, to retrieve a list of all password policy state properties for a user, you might want to use a command like:

$ bin/manage-account --hostname ds.example.com \
     --port 636 \
     --useSSL \
     --bindDN uid=admin,dc=example,dc=com \
     --targetDN uid=test.user,ou=People,dc=example,dc=com
Enter the bind password:

dn: uid=test.user,ou=People,dc=example,dc=com
base-command-line: manage-account get-all --targetDN uid=test.user,ou=People,dc=example,dc=com
result-code: 0
result-code-name: success
get-password-policy-dn: cn=Default Password Policy,cn=Password Policies,cn=config
get-account-is-usable: true
get-account-usability-notice-messages:
get-account-usability-warning-messages:
get-account-usability-error-messages:
get-password-changed-time: 20190610044447.266Z
get-account-is-disabled: false
get-account-activation-time:
get-seconds-until-account-activation:
get-account-is-not-yet-active: false
get-account-expiration-time:
get-seconds-until-account-expiration:
get-account-is-expired: false
get-password-is-expired: false
get-password-expiration-time:
get-seconds-until-password-expiration:
get-password-expiration-warned-time:
get-seconds-until-password-expiration-warning:
get-account-is-failure-locked: false
get-failure-lockout-time:
get-seconds-until-authentication-failure-unlock:
get-authentication-failure-times:
get-remaining-authentication-failure-count:
get-must-change-password: false
get-account-is-password-reset-locked: false
get-password-reset-lockout-time:
get-seconds-until-password-reset-lockout:
get-account-is-idle-locked: false
get-idle-lockout-time:
get-seconds-until-idle-lockout:
get-last-login-time:
get-last-login-ip-address:
get-password-changed-by-required-time:
get-seconds-until-required-password-change-time:
get-password-history-count: 0
get-grace-login-use-times:
get-remaining-grace-login-count: 0
get-has-retired-password: false
get-password-retired-time:
get-retired-password-expiration-time:
get-available-sasl-mechanisms: EXTERNAL
get-available-sasl-mechanisms: PLAIN
get-available-sasl-mechanisms: UNBOUNDID-CERTIFICATE-PLUS-PASSWORD
get-available-sasl-mechanisms: UNBOUNDID-EXTERNALLY-PROCESSED-AUTHENTICATION
get-available-otp-delivery-mechanisms:
get-has-totp-shared-secret: false
get-has-registered-yubikey-public-id: false
get-registered-yubikey-public-ids:
get-has-static-password: true

Password Policy-Related Controls

We also provide support for a number of request and response controls that allow for interaction with a user’s password policy state. They include:

  • Account Usable Control — May be included in a search request to indicate that the server should include a corresponding response control with each matching entry that indicates whether the account has a password policy state that would allow that user to authenticate.
  • Get Password Policy State Issues Control — May be included in a bind request to indicate that the bind response should include a response control with information about any errors, warnings, or notices pertaining to a user’s password policy state.
  • Password Expired Control — May be returned in the response to a bind request if the target user has an expired password or must change their password before they will be permitted to request any other operation.
  • Password Expiring Control — May be returned in the response to a bind request if the target user’s password will expire in the near future.
  • Password Policy Control — May be included in an add, bind, compare, modify, and password modify requests to indicate that the server should return a response control with information about any potential error or warning related to the target user’s password policy state.
  • Password Update Behavior Control — May be included in an add, modify, or password modify request to customize the behavior that the server should use when setting a new password.
  • Password Validation Details Control — May be included in an add, modify, or password modify request to indicate that the server should return extended information about the quality of the proposed password and any issues that prevented it from being accepted.
  • Retire and Purge Password Controls — May be included in a modify or password modify request to indicate that the user’s former password should be explicitly retired (so that it can continue to be used for a brief period of time as an alternative to the new password) or purged.
  • Suppress Operational Attribute Update Control — May be included in a request to indicate that the server should suppress updates to one or more operational attributes (including last login time and last login IP address, which are normally controlled by the password policy) that may have otherwise been updated by the operation.