!!! Overview [{$pagename}] is how [Microsoft Active Directory] determines [Password Expiration] [MsDS-UserPasswordExpiryTimeComputed] allows you to get the date the [MSA]'s [Password Expiration] [DateTime] !! [{$pagename}] [Algorithm] In determining if a [Password Expired] condition exists [Microsoft Active Directory], you must complete the following sub-tasks: * Determine if a user account password is set to expire. If the user's [Password never expires|DONT_EXPIRE_PASSWORD] option is enabled, there's no need to calculate [Password Expiration]. * Determine when user last changed their password ([pwd-Last-Set attribute]). * Determining what the [maximum password age|Max-Pwd-Age Attribute] is in the [Password Policy] or [AD DOMAIN] [Group Policy Object]. ** Now that you know that a user account password is set to expire and when last the user changed their password, the next step is to determine the length of time a user is allowed to use their password. ** This value is dictated by the [Password Policy] or [AD DOMAIN] [Group Policy Object] ** One small caveat here is if the maximum password age in the domain is set to 0, passwords in the domain do not expire. Your calculations must account for this exception. * Determine the current date. Knowing the current date, the date when the [password was last changed|pwd-Last-Set attribute], and the [max-Pwd-Age Attribute] in the [Domain root object] allows an application to calculate how many days remain before a password must be changed. The [algorithm] is essentially this: {{{ if "pwdLastSet" + "Max-Pwd-Age" >= "now" "password is expired" }}} Typically, the [Windows Client] monitors [Password Expiration] and will inform a user that the [password] is expiring soon when they perform a logon locally to [Windows Client]. It then provides a mechanism for [Password Change]. As long as the user changes the [password] before [Password Expired], they can continue to log in to the domain and all is good. However, if the password expires, then the user cannot log in again until an [Administrative Password Reset] occurs. This situation is not as straightforward for [LDAP] users, as there is no natural "login" process that informs users of pending [Password Expiration] and prompts them for a [Password Change]. Instead, it is completely up to the developer to supply both a notification and a means by which to advise a [Password Change] when using [LDAP]. Once a password has expired, all LDAP [Bind Requests] will fail (with [ERROR_PASSWORD_EXPIRED]) until a [Password Reset] is performed. !! [DONT_EXPIRE_PASSWORD] First we need to know if the entry's [DONT_EXPIRE_PASSWORD] from the [User-Account-Control Attribute]. The [DONT_EXPIRE_PASSWORD] value always takes precedence over other aspects of the [Password Policy]. We can find all the users from [LDAP] who do __NOT__ have [DONT_EXPIRE_PASSWORD] set by inspecting the [User-Account-Control Attribute Values] with a filter like: {{{ (&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=65536)) }}} This indicates that the user's password could expire. These are the users we would want to be included in [{$pagename}]. !! [pwdLastSet|pwd-Last-Set attribute] The pwdLastSet is the date, in [LargeInteger], when the password was last set on the entry. !! [maxPwdAge|max-Pwd-Age Attribute] The [maxPwdAge|max-Pwd-Age Attribute] attribute specifies the maximum amount of time that a password is valid. It is stored in [LargeInteger] and is time the [password] was set until the password expires. The value is obtained from the [Domain root object] when using [LDAP] the value of the [maxPwdAge|max-Pwd-Age Attribute] on the domain container. For our test server, it is: {{{ CN=Builtin,DC=mad,DC=willeke,DC=com | - pwdMaxAge=-37108517437440 }}} Which is "Sun, 19 Nov 1600 01:12:28 GMT", So I think we do not provide a [pwdMaxAge] for our domain. Now we need to enumerate the result from the query above that returns the entries which passwords could expire. Then each result you would need to perform a test like: {{{ if ((pwdMaxAge + pwdLastSet)) <=now()) { "Password is expired" } }}} You should also look at [MsDS-UserPasswordExpiryTimeComputed]. !! More Information There might be more information for this subject on one of the following: [{ReferringPagesPlugin before='*' after='\n' }]