Find out when your Password Expires

Few weeks ago I came across this question “How to find out an account’s password expiration date” in one of our internal mailing-list. This looks like a simple question, but when we tried to find the answer we realized it is not a trivial task. One of my colleagues pointed to this 22-printed page detailed MSDN article that describes how to find a user account’s password expiration date. The steps described in this article are a bit outdated. It does not take Fine-Grained Password policy (a new feature added in Windows 2008) into account while calculating the maximum password age. With the addition of fine grained password policy, this becomes an even more daunting task to do. Using AD Powershell this task can be achieved with ~40 lines of script-code. Here is function that calculates the password expiration date of a user object given its samAccountName, security identifier or DistinguishedName.

 function Get-XADUserPasswordExpirationDate() {

    Param ([Parameter(Mandatory=$true,  Position=0,  ValueFromPipeline=$true, HelpMessage="Identity of the Account")]

    [Object] $accountIdentity)

    PROCESS {

        $accountObj = Get-ADUser $accountIdentity -properties PasswordExpired, PasswordNeverExpires, PasswordLastSet

        if ($accountObj.PasswordExpired) {

            echo ("Password of account: " + $accountObj.Name + " already expired!")

        } else { 

            if ($accountObj.PasswordNeverExpires) {

                echo ("Password of account: " + $accountObj.Name + " is set to never expires!")

            } else {

                $passwordSetDate = $accountObj.PasswordLastSet

                if ($passwordSetDate -eq $null) {

                    echo ("Password of account: " + $accountObj.Name + " has never been set!")

                }  else {

                    $maxPasswordAgeTimeSpan = $null

                    $dfl = (get-addomain).DomainMode

                    if ($dfl -ge 3) { 

                        ## Greater than Windows2008 domain functional level

                        $accountFGPP = Get-ADUserResultantPasswordPolicy $accountObj

                        if ($accountFGPP -ne $null) {

                            $maxPasswordAgeTimeSpan = $accountFGPP.MaxPasswordAge

                        } else {

                            $maxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge

                        }

                    } else {

                        $maxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge

                    }

                    if ($maxPasswordAgeTimeSpan -eq $null -or $maxPasswordAgeTimeSpan.TotalMilliseconds -eq 0) {

                        echo ("MaxPasswordAge is not set for the domain or is set to zero!")

                    } else {

                        echo ("Password of account: " + $accountObj.Name + " expires on: " + ($passwordSetDate + $maxPasswordAgeTimeSpan))

                    }

                }

            }

        }

    }

}

Here are some sample usages of this function:

 PS AD:\> Get-XADUserPasswordExpirationDate testuser1
Password of account: testuser1 already expired!

PS AD:\> Get-XADUserPasswordExpirationDate JohnDoe
Password of account: John Doe expires on: 02/25/2010 13:03:20

Since the MSDN article explains the algorithm using a flow diagram, I too have tried creating a flow diagram that explains the logic used to compute the password expiration date of an account:

clip_image002

 

Hope you find this useful. Please leave a comment if you have any feedback on this topic or would like to see any other topic discussed in our blog.

 

Enjoy,

Swami

Comments

  • Anonymous
    June 08, 2010
    Will this script work on both 2003 and 2008?

  • Anonymous
    June 08, 2010
    Hello again,Having problems getting this to run on a Windows 2003 server.-> Have upgraded Powershell:PS C:Documents and SettingsAdministrator.EX2K3Desktop> $PSVersionTableName                           Value----                           -----CLRVersion                     2.0.50727.3082BuildVersion                   6.0.6002.18111PSVersion                      2.0WSManStackVersion              2.0PSCompatibleVersions           {1.0, 2.0}SerializationVersion           1.1.0.1PSRemotingProtocolVersion      2.1>Have set exectionpolicy to Unrestricted-> When trying to run the script it seems that the script doesn't run. How's that?:PS C:Documents and SettingsAdministrator.EX2K3Desktop> .GET-XADUserPasswordExpirationDate user1PS C:Documents and SettingsAdministrator.EX2K3Desktop>/G

  • Anonymous
    August 09, 2010
    @Greg BThe Active Directory module for Powershell is only supported on Windows Server 2008 R2 or Windows 7 OS. Please see the following for the installation details:blogs.msdn.com/.../installation

  • Anonymous
    March 16, 2011
    You can also read the (new in 2008) account attribute msDS-UserPasswordExpiryTimeComputed. This will tell you the password expiration date.

  • Anonymous
    January 17, 2012
    If the password is already expired, checking the "Password Never Expires" checkbox will un-expire the password until the user is located on a site with a DC.If the DC to be reachable over the VPN (which is a requirement for the lock/unlock suggestion that you have), why not just go ahead and change the password? Doing the change password will still cache the new password, so cached logons will work fine.http://www.lepide.com/

  • Anonymous
    July 31, 2012
    The comment has been removed

  • Anonymous
    August 16, 2012
    The net user command won't take note of fine grained password policies in a 2008r2 native domain. The attributes added to the schema that account for the functionality of fine grained password policies came after net user. That application has nothing that can account for those new attributes.

  • Anonymous
    January 29, 2014
    How do we use this in powershell?  I create a test4.ps1 file with the code from above pasted.  Then in powershell i run .Test4.ps1 Get-XADUserPasswordExpirationDate USERNAME and nothing shows up.  Am i running this correctly?Thanks

  • Anonymous
    March 24, 2014
    Thank you, This is an awesome scriptfunction, I'm most certainly adding this to my arsenal of scripts!Cheers,Matthew Kerfootwww.matthewkerfoot.com

  • Anonymous
    April 24, 2014
    Yours is too long. I just use old dos command on powershellnet user username <Enter> (for local user)net user username /domain <Enter> (for domain user)They will give you the same result.

  • Anonymous
    May 06, 2014
    Hi Swami,Thank you, the script is very useful and others for sharing ideas. If you wish to check password/ account expiration using GUI, you can checkout JiJi Password Expiration Notification Tool.Regards,Gopiwww.jijitechnologies.com

  • Anonymous
    May 26, 2014
    Go to boot from Windows CD, then go to command mode

  • Anonymous
    June 11, 2014
    Change the last else statement as follows:$expiryDate = Get-Date ($passwordSetDate + $maxPasswordAgeTimeSpan) -format D                       echo ("Password of account: " + $accountObj.Name + " expires on: " + $expiryDate)This returns the expiry date in a non-ambiguous format.

  • Anonymous
    July 06, 2014
    Powershell script just to find a password expiry? Seriously? Thi is so much easier:www.dolejarz.com/how-to-find-password-age-in-active-directory

  • Anonymous
    July 23, 2014
    The comment has been removed

  • Anonymous
    September 02, 2014
    Even though I was able to obtain the password expiration via a dos command/prompt, I do appreciate this PowerShell function. I had no issues getting it to light up, since we run a Windows 2008 R2 infrastructure. In addition, I am able to re-purpose much of the code.Thanks again M.Ali!

  • Anonymous
    September 05, 2014
    I have a strange situation where every now and again the if ($maxPasswordAgeTimeSpan -eq $null -or $maxPasswordAgeTimeSpan.TotalMilliseconds -eq 0) evaluates true.  not sure why.  Is there a way to manually set the $maxPasswordAgeTimeSpan equal to a 60 day time span as a work around?

  • Anonymous
    December 31, 2014
    Found this script to be extremely helpful during an implementation of FGPP.  I was having a problem with LDAP calls to active directory from an application that was returning results based off of the domain GPO rather than the FGPP.  When trying to identify the problem, the net user command was also misleading as it does not report values based off of the FGPP's.  This script was useful in finding and verifying the actual password expiration date for accounts with an FGPP applied.Thanks!

  • Anonymous
    January 14, 2015
    One liner : Get-ADUser $user -Properties "msDS-UserPasswordExpiryTimeComputed"Then, just convert to datetime.

  • Anonymous
    February 01, 2015
    Really Very good blog post, thanks for the useful  information about password expiration notification and find out all users who have password never expires via PowerShell command. I  also found good information from password-expiration-notification.blogspot.in whose provide the script to notify  users through email notification about their impending AD password expiry and get the complete  reports on the delivery status of password change reminder.

  • Anonymous
    March 06, 2015
    Kindly have a look at adsysnet ad inactive account tracker,. This tool notify the password and account expiration info . And options for scheduling actions on those ad user accounts.try this link, adsysnet.com/asn-active-directory-inactive-account-tracker-download.aspx

  • Anonymous
    October 01, 2015
    How do you run this script in powershell?

  • Anonymous
    October 28, 2015
    Steve - thanks for the one-liner.  The way powershell should work for something so simple!

  • Anonymous
    November 25, 2015
    Automatically computes the date and time, assigns it to column named PasswordExpirationDate get-aduser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -notlike "$" -and Mail -like "@"} -Properties msDS-UserPasswordExpiryTimeComputed,mail | select givenname,surname,samaccountname,@{name="PasswordExpirationDate";expression={([datetime]::FromFileTime($."msDS-UserPasswordExpiryTimeComputed"))}} | sort PasswordExpirationDate | ft Or this to save to .csv file get-aduser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -notlike "$" -and Mail -like "@"} -Properties msDS-UserPasswordExpiryTimeComputed,mail | select givenname,surname,samaccountname,@{name="PasswordExpirationDate";expression={([datetime]::FromFileTime($."msDS-UserPasswordExpiryTimeComputed"))}} | sort PasswordExpirationDate | export-csv -path passwordsexpiring.csv Want to know how many passwords expire tomorrow in a one liner? get-aduser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -notlike "$" -and Mail -like "@"} -Properties msDS-UserPasswordExpiryTimeComputed,mail | select givenname,surname,samaccountname,mail,@{name="PasswordExpirationDate";expression={([datetime]::FromFileTime($."msDS-UserPasswordExpiryTimeComputed"))}} | where {(($.PasswordExpirationDate).toshortdatestring()) -like (((get-date).adddays(1)).ToShortDateString())} | ft

  • Anonymous
    November 25, 2015
    Automatically computes the date and time, assigns it to column named PasswordExpirationDate.  Previous post would only display if they had an email address in AD.  Used the previous to send expiration notice to end user.   get-aduser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -notlike "$"} -Properties msDS-UserPasswordExpiryTimeComputed | select givenname,surname,samaccountname,@{name="PasswordExpirationDate";expression={([datetime]::FromFileTime($."msDS-UserPasswordExpiryTimeComputed"))}} | sort PasswordExpirationDate | ft Or this to save to .csv file get-aduser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -notlike "$"} -Properties msDS-UserPasswordExpiryTimeComputed | select givenname,surname,samaccountname,@{name="PasswordExpirationDate";expression={([datetime]::FromFileTime($."msDS-UserPasswordExpiryTimeComputed"))}} | sort PasswordExpirationDate | export-csv -path passwordsexpiring.csv Want to know how many passwords expire tomorrow in a one liner? get-aduser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -notlike "$"} -Properties msDS-UserPasswordExpiryTimeComputed | select givenname,surname,samaccountname,mail,@{name="PasswordExpirationDate";expression={([datetime]::FromFileTime($."msDS-UserPasswordExpiryTimeComputed"))}} | where {(($.PasswordExpirationDate).toshortdatestring()) -like (((get-date).adddays(1)).ToShortDateString())} | ft Hope it helps someone else,

  • Anonymous
    February 04, 2016
    Hey Swami, your scripts is gr8 and working. I'll like to have this script sending the email to user about password expire and it should be automated whereas above we need t manually run the Get-XADUserPasswordExpirationDate username command to get the details. Can you update the script and provide as i'm stuck up on it. Appreciate your help. Thanks, Admin