Password change notification when an AD user's password is about to expire

In this article, we'll show you how to find out when an Active Directory user account password 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's password in a domain has expired, the account is not locked out, but cannot be used to access domain resources until the user changes the expired password to a new one. Most of the time remote users run into problems with expired passwords as they cannot change their passwords with standard tools.The expiration time limit for a user's password in a domain, how often it must be changed (maximum password age), and complexity requirements are set in the AD domain password policy. These parameters are set in either the Default Domain Policy or the Specific Password Policy.
You can get the current password expiration policy settings on 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 it was last changed at the command prompt using the Network 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 m.
  • Password Expires – 7/1/2021 9:23:59 am
  • Changeable password – 09/10/2020 9:23:59 am
You can get the password expiration date for any user. To do this, you don't need administrator privileges or delegated privileges on the AD container with user accounts.
To see the settings of AD accounts, we will use a special PowerShell module for Active Directory that allows you to get values ​​of different attributes of AD objects (see how to install and import AD PowerShell module in Windows 10 and Windows Server 2012 R2 / 2016) .
With the Get-ADUser cmdlet, you can see the date the user's password was last changed and check if the PasswordNeverExpires option is set:
get-aduser jsmith -properties PasswordLastSet, PasswordNeverExpires, PasswordExpired |ft Name, PasswordLastSet, PasswordNeverExpires,PasswordExpired
  • PasswordLast is the date and time of the last password change;
  • Password never expires returns True if a user's password never expires;
  • Password expired – if a user's password has expired, return True , if the password is not expired return False .
You can check the time of the last password change in the Active Directory Users and Computers MMC graphical snap-in ( dsa.msc). To do this, open the 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 the password was changed. It is not clear when the password expires.

To get the password expiration date instead of the time it was last changed, use a special constructed AD attribute: msDS-UserPasswordExpiryTimeComputed . The msDS-UserPasswordExpiryTimeComputed value is automatically calculated based on the date of the last password change and the password policy of the domain.
The UserPasswordExpiryTimeComputed parameter returns the date in the TimeStamp format, so I use the FromFileTimefunction 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.
If the value of msDS-UserPasswordExpiryTimeComputed is 0, it means that pwdLastSet is empty (null) or equal to 0 (password has never been changed).
To get the password expiration dates for all users in 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
Returns a table with the list of active users, expiration date and time of 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's properties in AD (it's 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 for multiple users from a list in a text file at the same time:
$users=Get-Content "C:PSusers_password_never_expire.txt"
Foreach ($user in $users) {
Set-ADUser $user -PasswordNeverExpires:$True
}
You can display the list of all users with the regular password change option disabled:
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 setting that allows users to be notified that they need to change their passwords.
The policy is called Interactive logon: Prompt user to change password before expiration and is located in the GPO section: Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Local Policies -> Security options.
By default, the policy is enabled in Windows local settings and 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 you enable this policy, if the user's password expires, a notification to change a password will appear in the tray every time a user logs in.
Consider changing your password
Your password will expire in xx days.
You can also use a simple PowerShell script that automatically displays a dialog window with a message 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 will appear which you see after pressing Ctrl+Alt+Delor Ctrl+Alt+End(in case of an RDP/RDS connection).



Enable auto start of the PS script or run it as a GPO login script.

Password expiration email notification via Powershell
If you want to notify users about their password expiration via email, you can use this PowerShell script:
$Sender = "info@itinfs.com"
$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.itinfs.com"
$warnDays = (get-date).adddays(7)
$2Day = get-date
$Users = Get-ADUser -SearchBase 'OU=Users,OU=NewYork,DC=itinfs,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 verifies all active domain users whose passwords are about to expire. In 7 days before the password expires, a user starts receiving emails sent to the specified address in AD. Emails are sent until the password is changed or expires.
Run this PowerShell script regularly on any computer/server in your domain (easier to do with Task Scheduler). Of course, you'll need to add the sending host's IP address to the list of allowed senders (you can send email without authentication) on your SMTP server.

No comments

Powered by Blogger.