2021 Jun 20

Checking the *Real* Password Expiration Date

If you ever happened to have used ADAC for the users to set up their password policy to be different from the default for your domain, then you might have noticed the net user %username% /domain command will return not the expected value, as it checks the information quite differently. The script below will actually help to determine the real expiry date.

As reading from AD doesn't require the escalated privileges, it could be done with any account you like. For now, it will be using the command line, as it is more generic, faster, and just works. The GUI alternative is possible too, but it will be covered later.

For now, we can just have 2 lines of text (if you want to use credentials, then more of course, but as mentioned below, this is not significant for reading).

$user = Read-Host -Prompt "Username or part of it"
Get-ADUser -filter "samaccountname -like '*$user*' -and enabled -eq 'True' -and PasswordNeverExpires -eq 'False'" -Properties msDS-UserPasswordExpiryTimeComputed | Select-Object Name,samaccountname,@{n="Password Expiry Date";e={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | Sort-Object "Password Expiry Date"

What we have, is asking for input. You don't need to enter the colon or the space after - with the Read-Host -Prompt, PowerShell will take care of it for you. You can select to show you name, samaccountname and so on - whatever you prefer to see in the output. Sometimes, displayname is also fine. If this is a non-standard property - add it to the -Properties part of the command. The one we have there is what we exactly need - the expiry date. But originally, it shows the information in so-called ticks, and that won't make much sense, so in the structure @{n="Expiry Date";e={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} we are converting it to the human-readable view, which should be based on your system date settings.

With filtering, you should better use quotes, so you can search with wildcards, and have the matches included before the input, and after it. For example, if the input is "jd", then we will get the result for "jdoe", "abcjd", "abcjdoe" etc. Adding the -and PasswordNeverExpires -eq 'False' to the sctipt is optional - it will just skip the service accounts (which don't ususally have the expiration day), and they won't appear in the list with an empty field. But as far as we sort by the expiry date, they will be on the top, so you will see them separately from the rest. It's up to you, those scripts are rather adjustable.

Alternatively, you can add the function to your powershell profile. You can add something like this, just to ensure the user is entered. We also allow the pipeline input, so you can enter a few strings separated by coma, and then pipe them to the function without any extra arguments.

function Get-ADPasswordExpiryDate {
    process {
    Get-ADUser -filter "samaccountname -like '*$Username*' -and enabled -eq 'True' -and PasswordNeverExpires -eq 'False'" -Properties msDS-UserPasswordExpiryTimeComputed | Select-Object Name,sam*,@{n="Password Expiry Date";e={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | Sort-Object "Password Expiry Date"

An additional trick is to "demote" the mandatory parameter to a regular one, and specify it equals the current user. So, if the user provides input - perfect, they get a result. Alternatively, the function will return a value of the user who ran the command. What to choose from is your own liberty, you can achieve it changing the lines 2-5 from above to the following:


Open a new instance or PowerShell - and you can use it either with Get-PasswordExpiryDate user, or just Get-PasswordExpiryDate - the command line will ask you to input the user afterwards. You can notice the expiry date of 1601 - it happens when the password has been never set:

They posted on the same topic

Trackback URL : https://dykhl.in/trackback/8

This post's comments feed