Although Microsoft has removed the requirement to periodically change user passwords from its security baselines, most on-premises Active Directory domains have a policy that specifies the maximum age of a user’s password. Users often forget to change their expired passwords in time, resulting in unnecessary calls to IT support.
In this article, we’ll look at how to find out when a user account password on a domain will expire, and how to remind the user in advance that they need to change their password.
How to Get the User Password Expiration Date in Active Directory
The AD domain password policy settings determine the expiration date of a user’s password in a domain. To find the current settings of a domain’s password expiration policy, run the PowerShell command:
Get-ADDefaultDomainPasswordPolicy|select MaxPasswordAge
In this example, the maximum age of user passwords in the domain is 60 days.
The user properties in Active Directory only have the pwdLastSet attribute, which contains the date of the last password change (can be viewed in the ADUC console (dsa.msc
)-> AD Attribute Editor tab).
You can find out the expiration date of a user’s password in a domain using PowerShell (requires the AD PowerShell module), which allows getting the value of the msDS-UserPasswordExpiryTimeComputed attribute. The msDS-UserPasswordExpiryTimeComputed is a constructed attribute whose value is automatically calculated based on the date of the last password change and the domain password policy settings.
Get-ADUser -Identity jsmith -Properties msDS-UserPasswordExpiryTimeComputed, PasswordLastSet, PasswordNeverExpires, PasswordExpired |Select-Object -Property Name,PasswordLastSet, PasswordNeverExpires, PasswordExpired,@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
The cmdlet returns the values of the following attributes:
- PasswordLastSet — time of last password change;
- PasswordNeverExpires – returns True if the user’s password is set to Never Expire. This is one of the bit values of the UserAccountControl attribute;
- PasswordExpired – returns True if the user’s password has expired;
- ExpiryDate – the password expiry date.
List all users from a specific AD container (Organisational Unit) whose passwords have expired:
$Users = Get-ADUser -SearchBase 'OU=Users,OU=NewYork,DC=woshub,DC=com' -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties msDS-UserPasswordExpiryTimeComputed, PasswordLastSet
$Users | select Name, @{Name="ExpirationDate";Expression= {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}, PasswordLastSet | where ExpirationDate -lt (Get-Date)
Enable Active Directory Password Expiration Notification Policy
If you want to notify Active Directory users when they need to change their password, you can enable a separate Group Policy option in Windows.
The Interactive logon: Prompt user to change password before expiration policy is located in the GPO section: Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Local Policies -> Security Options.
This policy is enabled by default in the local Group Policy settings (gpedit.msc
). Notifications will start to appear 5 days before the password expires.
Once this policy is enabled, when a user’s password expires, a notification to change the password will appear in the system tray every time the user logs on to Windows. You can change the number of days before users see a password change notification.
Consider changing your password Your password will expire in xx days.
However, this message appears for a few seconds and is often ignored by users. Therefore, you can configure an additional pop-up notification for users when they need to change their password.
Show a Password Expiration Pop-up Notification with PowerShell
The following PowerShell script displays a pop-up message that prompts you to change your password if it expires in less than 5 days:
$DaysLeft = 5
try{
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
} catch {
Throw "Failed to load Windows Presentation Framework assemblies."
}
$curruser= Get-ADUser -Identity $env:username -Properties 'msDS-UserPasswordExpiryTimeComputed','PasswordNeverExpires'
if ( -not $curruser.'PasswordNeverExpires') {
$timediff=(new-timespan -start (get-date) -end ([datetime]::FromFileTime($curruser."msDS-UserPasswordExpiryTimeComputed"))).Days
if ($timediff -lt $DaysLeft) {
$msgBoxInput = [System.Windows.MessageBox]::Show("Your password will expire in "+ $timediff + " days!`nDoyou want to change it now?","Important!","YesNo","Warning")
switch ($msgBoxInput) {
'Yes' {
$Console = quser | Select-String -Pattern ">"| Select-String -Pattern "console" -Quiet
if ( $Console ) {
Start-Process -FilePath powershell -ArgumentList "-command Set-ADAccountPassword -Identity $env:username ; pause"
}
else {
cmd /c "C:\Windows\explorer.exe shell:::{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}"
}
}
'No' { }
}
}
}
If there are less than 5 days left before the password expires, the script will prompt the user to change the password. If the user clicks Yes, a check is made to see if the user is logged on at the computer console or remotely:
- If RDP sessions are detected, the user will see the Windows Security change password prompt, which can be accessed by pressing
Ctrl+Alt+Del
orCtrl+Alt+End
(used to change the password in an RDP session). - If the user is logged on locally (console session), the Set-ADAccountPassword cmdlet prompts you to change the password.
Schedule this PowerShell script to run through the Task Scheduler or run as a GPO logon script.
Send Account Expiration Email Notifications with PowerShell
If you want to notify users by sending them an e-mail when their password is about to expire, you can use this PowerShell script:
$Sender = "[email protected]"
$Subject = 'Important! Your password is about to expire!'
$BodyTxt1 = 'Your password for'
$BodyTxt2 = 'expires in '
$BodyTxt3 = 'days. Remember to change your password in advance. Contact the HelpDesk if you have any questions'
$smtpserver ="smtp.woshub.com"
$warnDays = (get-date).adddays(7)
$2Day = get-date
$Users = Get-ADUser -SearchBase 'OU=Users,OU=NewYork,DC=woshub,DC=com' -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties msDS-UserPasswordExpiryTimeComputed, EmailAddress, Name | select Name, @{Name ="ExpirationDate";Expression= {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}, EmailAddress
foreach ($user in $users) {
if (($user.ExpirationDate -lt $warnDays) -and ($2Day -lt $user.ExpirationDate) ) {
$lastdays = ( $user.ExpirationDate -$2Day).days
$EmailBody = $BodyTxt1, $user.name, $BodyTxt2, $lastdays, $BodyTxt3 -join ' '
Send-MailMessage -To $user.EmailAddress -From $Sender -SmtpServer $smtpserver -Subject $Subject -Body $EmailBody
}
}
The script finds all active domain users whose passwords are about to expire. In the 7 days before the password expires, a user will begin to receive emails sent to the address specified in the AD. Emails will continue to be sent until the password is changed or expires.
Run this PowerShell script regularly on any computer/server in your domain (it is easier to do it with the Task Scheduler). In this example, we don’t use SMTP authentication in the script. So should add this host IP to the list of allowed senders on your SMTP server to allow email to be sent without authentication.
5 comments
Hi, I tried your PowerShell script that automatically shows a dialog window with the prompt to change a password if it expires in less than 5 days: I change it from 5 days to 10 days and notify the user’s password to expire in 153470 days?
Can you help me with this. we struggle with VPN users changing their passwords.
Same problem as Wayne
these password reset notification alert stay for 5second only, how can we make this notification stay longer? how do we enable on server end to let this notification stay longer
Are you talking about the “Interactive Logon: Prompt user to change password before expiration” policy?
I do not think that’s possible. You can use email notifications instead.
should cmd /c “explorer shell:::{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}” work on Windows 10?
I dont see the cntl alt del screen