In this article we’ll show how to find out when a password of an Active Directory user account expires using PowerShell, how to set a password to never expire (PasswordNeverExpires = True
), and notify users in advance to change their password.
If a user password in a domain has expired, the account is not locked, but it cannot be used to access domain resources until the user changes the expired password to a new one. The most often, remote users come across problems with expired passwords, since they cannot change their passwords using standard tools.
You can get the current password expiration policy settings in a domain using this PowerShell command:
Get-ADDefaultDomainPasswordPolicy|select MaxPasswordAge
In our example, the maximum user password age in the domain is 60 days.
How to Get a User Password Expiration Date in Active Directory?
You can view the password age and the date when it was changed last time in the command prompt using the Net user command:
net user jsmith /domain
You can find the information you need in these lines:
- Password last set — 9/9/2020 9:23:59 AM
- Password expires — 1/7/2021 9:23:59 AM
- Password changeable — 9/10/2020 9:23:59 AM
To view the settings of AD accounts, we will use a special PowerShell for Active Directory module that allows you to get values of different AD object attributes (see how to install and import the AD PowerShell module in Windows 10 and Windows Server 2012 R2/2016).
Using the Get-ADUser cmdlet, you can view the date when the user’s password was changed last time and check if the PasswordNeverExpires option is set:
get-aduser jsmith -properties PasswordLastSet, PasswordNeverExpires, PasswordExpired |ft Name, PasswordLastSet, PasswordNeverExpires,PasswordExpired
- PasswordLastSet is the date and time of the last password change;
- PasswordNeverExpires returns True if a user password never expires;
- PasswordExpired – if a user password has expired, it returns True, if the password is not expired, it returns False.
dsa.msc
). To do it, open user properties, go to the Attribute Editor tab and check the value of the pwdLastSet attribute.But as you can see, the MMC snap-in only shows the time when the password was changed. It is not clear when the password expires.
To get the password expiry date instead of the time it was last changed, use a special constructed AD attribute: msDS-UserPasswordExpiryTimeComputed. The msDS-UserPasswordExpiryTimeComputed value is calculated automatically based on the date of the last password change and the domain password policy.
The UserPasswordExpiryTimeComputed parameter returns the date in the TimeStamp format, so I use the FromFileTime
function to convert it to human readable value:
Get-ADUser -Identity jsmith -Properties msDS-UserPasswordExpiryTimeComputed | select-object @{Name="ExpirationDate";Expression= {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed") }}
Thus, we got a user password expiration date.
To get password expiry dates for all users from the specific container (OU) in AD, you can use the following PowerShell script:
$Users = Get-ADUser -SearchBase 'OU=Users,OU=NewYork,DC=woshub,DC=com' -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties msDS-UserPasswordExpiryTimeComputed, PasswordLastSet, CannotChangePassword
$Users | select Name, @{Name="ExpirationDate";Expression= {[datetime]::FromFileTime ($_."msDS-UserPasswordExpiryTimeComputed")}}, PasswordLastSet
It results in a table with the list of active users, expiration date and time of the last password change.
You can display only the list of users with expired passwords:
$Users = Get-ADUser -SearchBase 'OU=Users,OU=NewYork,DC=woshub,DC=com' -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties msDS-UserPasswordExpiryTimeComputed, PasswordLastSet, CannotChangePassword
foreach($user in $Users){
if( [datetime]::FromFileTime($user."msDS-UserPasswordExpiryTimeComputed") -lt (Get-Date)) {
$user.Name
}
}
How to Set AD User Password to Never Expire?
If you want to set a permanent password for an account, check the Password Never Expires option in the user properties in AD (it is one of the bit values of the UserAccoutControl attribute).
Or you can enable this option with PowerShell by setting the user attribute:
Get-ADUser jsmith | Set-ADUser -PasswordNeverExpires:$True
You can set the Password Never Expires option at once for multiple users from a list in a text file:
$users=Get-Content "C:\PS\users_password_never_expire.txt"
Foreach ($user in $users) {
Set-ADUser $user -PasswordNeverExpires:$True
}
You can display the list of all users with the disabled regular password change option:
Get-ADUser -filter * -properties Name, PasswordNeverExpires | where {$_.passwordNeverExpires -eq "true" } | Select-Object DistinguishedName,Name,Enabled |ft
Active Directory Password Expiration Notification Policy
Windows has a special Group Policy parameter that allows to notify users that they must change their passwords.
The policy is called Interactive logon: Prompt user to change password before expiration and is located under the GPO section: Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Local Policies -> Security Options.
By default, the policy is enabled on the local Windows settings, and the notifications start to appear 5 days before a password expires. You can change the number of days that users will see a password change notification.
After enabling this policy, if the user’s password expires, a notification to change a password will appear in the tray each time a user logs on.
Consider changing your password Your password will expire in xx days.
You can also use a simple PowerShell script that automatically shows a dialog window with the prompt to change a password if it expires in less than 5 days:
Add-Type -AssemblyName PresentationFramework
$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 5) {
$msgBoxInput = [System.Windows.MessageBox]::Show("Your password expires in "+ $timediff + " days!`nDo you want to change it now?","Important!","YesNo","Warning")
switch ($msgBoxInput) {
'Yes' {
cmd /c "explorer shell:::{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}"
}
'No' { }
}
}
}
If a user clicks YES, a Windows Security window appears that you see after pressing Ctrl+Alt+Del
or Ctrl+Alt+End
(in case of an RDP/RDS connection).
Enable automatic startup for the PS script or run it as a GPO logon script.
Password Expiration Email Notification via Powershell
If you want to notify users about their password expiry by email, you can use this PowerShell script:
$Sender = "[email protected]"
$Subject = 'Important! Your password expires soon!'
$BodyTxt1 = 'Your password for'
$BodyTxt2 = 'expires in '
$BodyTxt3 = 'days. Remember to change your password in advance. If you have other questions, contact the HelpDesk.'
$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 checks all active domain users whose passwords are about to expire. In 7 days before the password expires, a user starts to get emails sent to the address specified in AD. Emails are sent until the password is changed or gets expired.
Run this PowerShell script regularly on any computer/server in your domain (it is easier to do it with the Task Scheduler). Of course, you will have to add the IP address of the host that is sending emails to the allowed senders list (can send email without authentication) on your SMTP server.
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