IT Administration

🔁 Reset AD Passwords in Bulk from CSV with Force-Change-at-Logon

By Alex Chen, Instant Password Generator · 9 Jun 2026 · 8 min read · 1,850 words

The Problem: Bulk Reset Is Different from Bulk Creation

Creating new AD users with generated passwords is one workflow. Resetting existing users — especially after a security incident, a forgotten-password wave, or an offboarding sweep — is a completely different challenge:

This guide covers the complete end-to-end workflow: generate unique secure passwords → build the reset CSV → run the PowerShell reset script → verify every account.

⚡ Generate Bulk Passwords Now →

What You'll Need

Step 1: Generate Unique Passwords

Open the Instant Password Generator and configure:

  1. Count: Match the number of users whose passwords you're resetting
  2. Length: 20+ characters to exceed all domain password policies and NIST SP 800-63B minimums
  3. Character classes: All four — uppercase, lowercase, numbers, symbols
  4. Format: CSV export — the tool outputs index,"password"
Why unique passwords per user matter: If you're resetting because of a suspected credential compromise, using the same temporary password for everyone recreates the vulnerability. Each user must get a unique, cryptographically random password — which is exactly what the generator produces.

Step 2: Build the Reset CSV

Create a reset.csv with this structure. The sam column is the sAMAccountName — the pre-Windows 2000 logon name:

sam,password,ou
jsmith,P@$$w0rd123!,OU=Users,DC=contoso,DC=com
agarcia,Kj9#mB2$xL7!,OU=Users,DC=contoso,DC=com
bnguyen,Zp4&qR8*vF2!,OU=Sales,DC=contoso,DC=com
mwilliams,Xm3@zK1!qL8,OU=Users,DC=contoso,DC=com

To merge your generated passwords with existing user data:

# Merge generated passwords with user SAM list
$passwords = Import-Csv "passwords.csv" | Select-Object -ExpandProperty password
$users = @("jsmith", "agarcia", "bnguyen")

$output = for ($i = 0; $i -lt $users.Count; $i++) {
    [PSCustomObject]@{
        sam      = $users[$i]
        password = $passwords[$i]
        ou       = "OU=Users,DC=contoso,DC=com"
    }
}
$output | Export-Csv "reset.csv" -NoTypeInformation

Step 3: Bulk Reset Passwords

This is the core script. It reads the CSV, resets each user's password, and forces a change at next logon:

Import-Module ActiveDirectory

$users = Import-Csv "reset.csv"

foreach ($user in $users) {
    $securePwd = ConvertTo-SecureString $user.password -AsPlainText -Force

    try {
        Set-ADAccountPassword -Identity $user.sam `
            -NewPassword $securePwd `
            -Reset `
            -ErrorAction Stop

        Set-ADUser -Identity $user.sam `
            -ChangePasswordAtLogon $true

        Write-Host "✓ Reset password for $($user.sam) with force-change-at-logon" -ForegroundColor Green
    }
    catch {
        Write-Host "✗ Failed for $($user.sam): $_" -ForegroundColor Red
    }
}

Key Parameters Explained

ParameterPurpose
-ResetForces a password reset even if the user doesn't know their current password. Critical for lockout/compromise scenarios.
-NewPasswordThe generated password as a secure string. Must be complex enough to meet domain policy.
-ChangePasswordAtLogon $trueEnsures the generated password is one-time use. The user creates their own password on first login.
-IdentityAccepts sAMAccountName, UPN, or Distinguished Name. We use sAMAccountName from the CSV.

Step 4: OU-Specific Scenarios

Reset All Users in a Specific OU

# Reset every user in the Sales OU
$ou = "OU=Sales,DC=contoso,DC=com"
Get-ADUser -Filter * -SearchBase $ou | ForEach-Object {
    $securePwd = ConvertTo-SecureString "NewTempP@ss123!" -AsPlainText -Force
    Set-ADAccountPassword -Identity $_.SamAccountName -NewPassword $securePwd -Reset
    Set-ADUser -Identity $_.SamAccountName -ChangePasswordAtLogon $true
    Write-Host "Reset $($_.SamAccountName)" -ForegroundColor Green
}

Reset Only Disabled or Locked-Out Accounts

# Find and reset locked-out users
$locked = Search-ADAccount -LockedOut
foreach ($user in $locked) {
    $securePwd = ConvertTo-SecureString "Unl0ck@2026!" -AsPlainText -Force
    Set-ADAccountPassword -Identity $user.SamAccountName -NewPassword $securePwd -Reset
    Set-ADUser -Identity $user.SamAccountName -ChangePasswordAtLogon $true
    Unlock-ADAccount -Identity $user.SamAccountName
    Write-Host "Unlocked and reset $($user.SamAccountName)" -ForegroundColor Yellow
}

Bulk Reset from a Text File (One User Per Line)

# Single-column user list
$users = Get-Content "users.txt"
$passwords = (Import-Csv "passwords.csv").password

for ($i = 0; $i -lt $users.Count; $i++) {
    $securePwd = ConvertTo-SecureString $passwords[$i] -AsPlainText -Force
    Set-ADAccountPassword -Identity $users[$i] -NewPassword $securePwd -Reset
    Set-ADUser -Identity $users[$i] -ChangePasswordAtLogon $true
    Write-Host "Reset $($users[$i])" -ForegroundColor Green
}

Step 5: Verification

After running the bulk reset, verify every account:

# Check users who still don't require password change
Get-ADUser -Filter {PasswordNeverExpires -eq $false -and Enabled -eq $true} `
    -Properties pwdLastSet | Where-Object { $_.pwdLastSet -eq 0 } | `
    Select-Object Name, SamAccountName

# Confirm specific user was reset
Get-ADUser jsmith -Properties PasswordLastSet, pwdLastSet, LastLogonDate

# Count recently reset users
$since = (Get-Date).AddHours(-1)
Get-ADUser -Filter {PasswordLastSet -ge $since} -Properties PasswordLastSet | `
    Measure-Object | Select-Object -ExpandProperty Count
Security note: The CSV file containing plaintext generated passwords is sensitive data. Delete it after the reset completes. The generator never transmits passwords to any server — all generation happens client-side in your browser — so the CSV is the only copy in existence.

Troubleshooting

ErrorCauseFix
"Access denied"Insufficient AD permissionsRun as domain admin or delegate reset-password for the target OU
"Cannot find an object with identity"sAMAccountName doesn't exist or is misspelledVerify user exists: Get-ADUser user. Check CSV for typos.
"The password does not meet policy requirements"Password violates domain password policyGenerate with all 4 character classes at 20+ characters
"The user account is disabled"Account is inactiveUse -Enabled $true or enable via Enable-ADAccount
⚡ Generate 50 Unique Passwords Now →

Next Article in This Series

This is part of the Active Directory password management series:

For teams managing passwords across multiple users, a shared credential vault simplifies the whole lifecycle. NordPass Business integrates directly with AD and provides secure password sharing, access groups, and breach monitoring.

Disclosure: If you purchase through the NordPass link above, we may earn a commission at no extra cost to you. All affiliate links are marked with "sponsored" per FTC and ASA guidelines.

More Password Security Tools

🔑 SecureKeyGen⚔️ TitanPasswords🛡️ Best Password Generator🔐 Free Strong Password🗝️ Iron Vault Keys🔑 Random Pwd Tool👨‍👩‍👧‍👦 Safe Pass Builder🛡️ Trusty Password⚙️ WorkPassword🔑 SecureKeyGen.org
We use essential cookies only. Learn more