Microsoft 365 offers self-service capabilities that empower users to manage their own passwords without administrator involvement. But with this convenience comes a need for visibility — especially when it comes to auditing and security. In this blog, we’ll walk you through what Password Self Service is, how to enable it, and most importantly — how to track who changed or reset their password using Microsoft Entra ID, Graph PowerShell, or our simple GUI tool.
Password Self Service in Microsoft 365 allows users to:
This feature is powered by Microsoft Entra ID (formerly Azure AD) and helps reduce helpdesk load while increasing user independence.
To enable password self-service for your users:
There are three ways to view self-service password activity — ranging from the Entra portal to automation via PowerShell.
You can manually track password changes and resets via the Entra Admin Center:
You can use the Microsoft Graph PowerShell SDK to script and automate the reporting process.
We’ve written a detailed post that explains how to fetch these events directly from audit logs: Self Service Password Change – Graph PowerShell Script
This method provides: i) Scripted control, ii) Export Capabilities and iii) Scheduled monitoring potential.
For admins who prefer not to write code, we’ve created a ready-to-use GUI tool that does it all for you — no scripting required!
Note: This works only for Windows users.
PowerShell Script: SelfServicePasswordChangeAudit_GUI.ps1
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $form = New-Object System.Windows.Forms.Form $form.Text = "Self-Service Password Change Audit" $form.Size = New-Object System.Drawing.Size(750, 500) $form.StartPosition = "CenterScreen" $fetchButton = New-Object System.Windows.Forms.Button $fetchButton.Text = "Fetch Password Changes" $fetchButton.Location = New-Object System.Drawing.Point(20, 20) $fetchButton.Size = New-Object System.Drawing.Size(180, 30) $form.Controls.Add($fetchButton) $exportButton = New-Object System.Windows.Forms.Button $exportButton.Text = "Export to CSV" $exportButton.Location = New-Object System.Drawing.Point(220, 20) $exportButton.Size = New-Object System.Drawing.Size(120, 30) $exportButton.Enabled = $false $form.Controls.Add($exportButton) $dataGrid = New-Object System.Windows.Forms.DataGridView $dataGrid.Location = New-Object System.Drawing.Point(20, 70) $dataGrid.Size = New-Object System.Drawing.Size(690, 360) $dataGrid.ReadOnly = $true $dataGrid.AllowUserToAddRows = $false $dataGrid.AutoSizeColumnsMode = "Fill" $form.Controls.Add($dataGrid) $script:PwdLogs = @() $fetchButton.Add_Click({ $fetchButton.Enabled = $false $exportButton.Enabled = $false $dataGrid.DataSource = $null try { Connect-MgGraph -Scopes "AuditLog.Read.All" -ErrorAction Stop $ChangePwdLogs = Get-MgAuditLogDirectoryAudit -Filter "category eq 'UserManagement' and activityDisplayName eq 'Change password (self-service)'" -All $script:PwdLogs = @() foreach ($log in $ChangePwdLogs) { $pwdChangedTime = $log.ActivityDateTime $userPrincipalName = "" if ($log.TargetResources.Count -gt 0 -and $log.TargetResources[0].UserPrincipalName) { $userPrincipalName = $log.TargetResources[0].UserPrincipalName } $result = if ($log.Result -eq "success") { "Success" } else { "Failure" } $script:PwdLogs += [PSCustomObject]@{ "Password Changed Time" = $pwdChangedTime "User ID" = $userPrincipalName "Result Status" = $result } } if ($script:PwdLogs.Count -gt 0) { $dataTable = New-Object System.Data.DataTable $script:PwdLogs[0].psobject.properties.name | ForEach-Object { [void]$dataTable.Columns.Add($_) } foreach ($item in $script:PwdLogs) { $row = $dataTable.NewRow() foreach ($col in $dataTable.Columns) { $row[$col.ColumnName] = $item.($col.ColumnName) } $dataTable.Rows.Add($row) } $dataGrid.DataSource = $dataTable $exportButton.Enabled = $true } else { [System.Windows.Forms.MessageBox]::Show("No self-service password change records found.", "Info", "OK", "Information") } } catch { [System.Windows.Forms.MessageBox]::Show("Error: $($_.Exception.Message)", "Error", "OK", "Error") } $fetchButton.Enabled = $true }) $exportButton.Add_Click({ $saveDialog = New-Object System.Windows.Forms.SaveFileDialog $saveDialog.Filter = "CSV Files (*.csv)|*.csv" $saveDialog.Title = "Save Password Change Report" $saveDialog.FileName = "SelfServicePasswordChanges.csv" if ($saveDialog.ShowDialog() -eq "OK") { $script:PwdLogs | Export-Csv -Path $saveDialog.FileName -NoTypeInformation [System.Windows.Forms.MessageBox]::Show("Export completed.", "Export", "OK", "Information") } }) [void]$form.ShowDialog()
How to Use
Click and Play the GIF to see the tool in action
Tracking self-service password events is a vital part of Microsoft 365 security hygiene. Whether you're an IT admin, security analyst, or compliance officer — knowing who changed their password, when, and whether it succeeded can help you:
Choose the method that works best for you — whether it’s through Entra logs, Graph PowerShell, or our easy GUI.
Did You Know? Managing Microsoft 365 applications is even easier with automation. Try our Graph PowerShell scripts to automate tasks like generating reports, cleaning up inactive Teams, or assigning licenses efficiently.
Ready to get the most out of Microsoft 365 tools? Explore our free Microsoft 365 administration tools to simplify your administrative tasks and boost productivity.
© Your Site Name. All Rights Reserved. Design by HTML Codex