none
How to force Windows password to expire when user is log in ? RRS feed

  • Question

  • Hi. I'm not the best one on scripting, so that's why I really need your help..

    I need to built a script (VB or Batch) that will force a user Windows password to be expired in real time. We have some issues when Windows password is expired in the middle of the user sessions that block all shared access for our home application. We have to use this script for testing test account and force them to be expired like our users issues.

    I know that I can change in AD the attribute "pwdLastSet" to "0" or "-1".

    I would prefer something that I can run everytime I need for my test..

    Hope someone can help me.. :)

    Thanks

    • Moved by Bill_Stewart Friday, March 9, 2018 7:31 PM Goal is not clear/abandoned
    Monday, September 11, 2017 7:09 PM

All replies

  • Even if you expire the user password, by assigning 0 to pwdLastSet, they won't need to change it until they next logon. You would need to force a logoff.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    • Proposed as answer by I.T Delinquent Tuesday, September 12, 2017 8:13 AM
    Monday, September 11, 2017 7:36 PM
  • Hi. I had a similar problem with password expiration during workday and messing things up. The easiest way is to set script as Scheduled Task Item which will run after work hours and check if any of AD users have to change their password in next 24h. After that selected users will be forced to change their password on first login in the morning

    Script is a modification of: community spiceworks com/topic/328002-make-all-passwords-expire-at-midnight

    $SearchBase = "OU=,DC=,DC=" #set your information
    $Age = 0
    $filename = "" #report txt path
    
    cls
    $SearchSplat = @{
        Filter = "*"
    }
    If ($SearchBase)
    {   $SearchSplat.Add("SearchBase",$SearchBase)
        $SearchSplat.Add("SearchScope","Subtree")
    }
    
    #Load RSAT
    Try { Import-Module ActiveDirectory -ErrorAction Stop }
    Catch { Write-Host "Unable to load Active Directory module, is RSAT installed?"; Exit }
    
    #Find out the global domain Password Age
    $DomainMode = (Get-ADDomain).DomainMode.Value__
    $maxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
    
    #Loop through all users, ignore users who are disabled, have their password set to never expire or have never set a password.
    $Results = @()
    ForEach ($User in (Get-ADUser @SearchSplat -Properties PasswordExpired,PasswordLastSet,PasswordNeverExpires,LastLogonDate))
    {   If ($User.PasswordNeverExpires -or $User.PasswordLastSet -eq $null -or $User.Enabled -eq $false)
    	{	Continue
    	}
        If ($DomainMode -ge 3) 
    	{
    		$accountFGPP = $null
    		$accountFGPP = Get-ADUserResultantPasswordPolicy $User
        	If ($accountFGPP -ne $null) 
    		{	$ResultPasswordAgeTimeSpan = $accountFGPP.MaxPasswordAge
        	} 
    		Else 
    		{	$ResultPasswordAgeTimeSpan = $maxPasswordAgeTimeSpan
        	}
    	}
    	$Expiration = $User.PasswordLastSet + $ResultPasswordAgeTimeSpan
    	If ((New-TimeSpan -Start (Get-Date) -End $Expiration).Days -le $Age)
    	{	$Results += New-Object PSObject -Property @{
    			'Last Name' = $User.Surname
    			'First Name' = $User.GivenName
    			'UserName' = $User.SamAccountName
    			'Password Expiration Date' = $Expiration
    			'Last Logon Date' = $User.LastLogonDate
                }
            Set-ADUser $User -ChangePasswordAtLogon $true -WhatIf  #comment -WhatIf for production
    	}
    }
    
    #If we have something and want to save the report
    If ($Results)
    {  
    $Raport = $Results | Select 'Last Name','First Name','UserName','Password Expiration Date','Last Logon Date' | Out-file $filename
    }



    • Edited by Michal Barcz Wednesday, September 13, 2017 6:19 AM
    Wednesday, September 13, 2017 6:17 AM
  • Here is a batch file that will configure a specified user so they must change their password the next time they logon:

    @echo off
    dsquery user domainroot -samid %1 | dsmod user -mustchpwd yes
    

    You specify the user be sAMAccountName, which is the "pre-Windows 2000 logon" name. A VBScript solution would allow for error checking, but is much longer. In this example you can either specify the "pre-Windows 2000 logon" name at the command line when you launch the script, or it will prompt for the name. An error message is given if the user is not found:

    ' Script to expire a specified user's password.
    
    Option Explicit
    
    Dim strName, objRootDSE, strDNSDomain, adoCommand, adoConnection, strBase, strFilter
    Dim strAttributes, strQuery, adoRecordset, strDN, objUser
    
    ' Retrieve computer name.
    If (Wscript.Arguments.Count = 1) Then
        strName = Wscript.Arguments(0)
    Else
        strName = InputBox("Enter user pre-Windows 2000 logon name")
    End If
    
    ' Determine local domain.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("DefaultNamingContext")
    
    ' Setup ADO objects.
    Set adoCommand = CreateObject("ADODB.Command")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"
    Set adoCommand.ActiveConnection = adoConnection
    
    ' Search entire Active Directory domain.
    strBase = "<LDAP://" & strDNSDomain & ">"
    
    ' Filter on user with specified sAMAccountName.
    strFilter = "(&(objectCategory=person)(objectClass=user)" _
        & "(sAMAccountName=" & strName & "))"
    
    ' Comma delimited list of attribute values to retrieve.
    strAttributes = "distinguishedName"
    
    ' Construct the LDAP syntax query.
    strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
    adoCommand.CommandText = strQuery
    adoCommand.Properties("Page Size") = 100
    adoCommand.Properties("Timeout") = 30
    adoCommand.Properties("Cache Results") = False
    
    ' Run the query.
    Set adoRecordset = adoCommand.Execute
    
    ' Enumerate the resulting recordset.
    Do Until adoRecordset.EOF
        ' Retrieve values.
        strDN = adoRecordset.Fields("distinguishedName").Value
        adoRecordset.MoveNext
    Loop
    
    ' Clean up.
    adoRecordset.Close
    adoConnection.Close
    
    ' Bind to the user object in AD.
    On Error Resume Next
    Set objUser = GetObject("LDAP://" & strDN)
    If (Err.Number <> 0) Then
        Wscript.Echo "User " & strName & " not found"
        Wscript.Quit
    End If
    
    ' Configure the user so password is expired.
    objUser.pwdLastSet = 0
    objUser.SetInfo
    

    A similar PowerShell solution can take advantage of the AD modules, so it is much simpler:

    If ($Args.Count -eq 1)
    {
        $Name = $Args[0]
    }
    Else
    {
        $Name = Read-Host "Enter Pre-Windows 2000 name of the user"
    }
    
    Set-ADUser -Identity $Name -ChangePasswordAtLogon $True
    


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Tuesday, September 19, 2017 3:22 PM