This PowerShell script can be used to ingest a .csv list of users by UPN, and create a new .csv with each user and their last sign in date. I used this script to clean up some old inactive service accounts.
Connect to Graph API with the following scopes.
Connect-MgGraph -Scopes $Scopes
$Scopes = @(
"User.Read.All",
"Directory.Read.All",
"AuditLog.Read.All"
)
Run script below, making sure to point InputFile to your list of user’s in the first column of a .csv, and Output to where you want the final .csv
# Assuming the input CSV has the UPNs in the first column without a header
$InputFile = "C:\scripting\disabledusers.csv"
$OutputFile = "C:\scripting\BulkSignInActivity.csv"
# Read UPNs from the input CSV
$UPNList = Import-Csv -Path $InputFile -Header "UPN"
# Initialize an array to hold the results
$Results = @()
$TotalUPNs = $UPNList.Count
$ProcessedUPNs = 0
foreach ($UPN in $UPNList) {
# Update progress
$ProcessedUPNs++
Write-Progress -Activity "Processing UPNs" -Status "$ProcessedUPNs of $TotalUPNs" -PercentComplete (($ProcessedUPNs / $TotalUPNs) * 100)
try {
# Retrieve the user's Object ID from their UPN
$User = Get-MgUser -Filter "userPrincipalName eq '$($UPN.UPN)'"
# If user is found, retrieve sign-in activity
if ($User) {
$UserData = Get-MgUser -UserId $User.Id -Property "SignInActivity"
$Result = $UserData.SignInActivity |
Select-Object @{Name='UPN'; Expression={$UPN.UPN}},
LastNonInteractiveSignInDateTime,
LastNonInteractiveSignInRequestId,
LastSignInDateTime,
LastSignInRequestId
# Add result to the results array
$Results += $Result
}
} catch {
Write-Host "Failed to process UPN: $($UPN.UPN)"
}
}
# Final update for progress
Write-Progress -Activity "Processing UPNs" -Completed
# Export the results to CSV
$Results | Export-Csv -Path $OutputFile -NoTypeInformation