Entra / Microsoft 365 · Users & guests
Report last account sign in mg
Fetch user account sign in data using the Microsoft Graph SDK for PowerShell.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -TenantId xxxxx-axxad-acadd-ddaadda -Scope Auditlog.Read.All
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
Connect-MgGraph -TenantId xxxxx-axxad-acadd-ddaadda -Scope Auditlog.Read.AllSelect-MgProfile beta # Beta needed to get more informtion from the Graph$Details = Get-MgContext$Scopes = $Details | Select -ExpandProperty Scopes$Scopes = $Scopes -Join ", "$ProfileName = (Get-MgProfile).Name$OrgName = (Get-MgOrganization).DisplayNameCLSWrite-Host "Microsoft Graph Connection Information"Write-Host "--------------------------------------"Write-Host " "Write-Host ("Connected to Tenant {0} ({1}) as account {2}" -f $Details.TenantId, $OrgName, $Details.Account)Write-Host "+-------------------------------------------------------------------------------------------------------------------+"Write-Host ("Profile set as {0}. The following permission scope is defined: {1}" -f $ProfileName, $Scopes)Write-Host ""Write-Host "Finding Azure AD Users"[array]$Users = Get-MgUser -AllIf ($Users.Count -eq 0) { Write-Host "Sorry, no Azure AD user info fetched"; break}CLS$ProgressDelta = 100/($Users.count); $PercentComplete = 0; $UserNumber = 0Write-Host ("{0} accounts to process..." -f $Users.Count)CLS;$Report = [System.Collections.Generic.List[Object]]::new();$CSVOutput = "C:\temp\LastAccountSignIn.CSV"ForEach ($User in $Users) { # See if we can find the last sign in record for an account$UserNumber++$PercentComplete += $ProgressDelta$UserStatus = $User.DisplayName + " ["+ $UserNumber +"/" + $Users.Count + "]"Write-Progress -Activity "Processing user" -Status $UserStatus -PercentComplete $PercentComplete[array]$LastSignIn = Get-MgAuditLogSignIn -Filter "UserId eq '$($User.Id)'" -Top 1If ($LastSignIn) { # We found a sign in record, so report it$ReportLine = [PSCustomObject][Ordered]@{Name = $LastSignIn.UserDisplayNameUPN = $LastSignIn.UserPrincipalNameId = $LastSignIn.UserIdUserType = $User.UserTypeAccountCreated = $User.CreatedDateTimeSignInDate = $LastSignIn.CreatedDateTimeDaysSince = ($LastSignIn.CreatedDateTime | New-TimeSpan).DaysLocation = $LastSignIn.Location.CityApp = $LastSignIn.AppDisplayNameClient = $LastSignIn.ClientAppUsedIPAddress = $LastSignIn.IPAddressIsInteractive = $LastSignIn.IsInterActiveCAAccess = $LastSignIn.ConditionalAccessStatusRiskState = $LastSignIn.RiskState }$Report.Add($ReportLine) } #End ifElse { # No sign in record found, so we report that"$ReportLine = [PSCustomObject][Ordered]@{Name = $User.UserDisplayNameUPN = $User.UserPrincipalNameId = $User.IdUserType = $User.UserTypeAccountCreated = $User.CreatedDateTimeSignInDate = "No sign in data found"DaysSince = "N/A"App = "N/A"Client = "N/A"IPAddress = "N/A"IsInteractive = "N/A"CAAccess = "N/A"RiskState = "N/A" }$Report.Add($ReportLine) } #End Else} #End ForEach$Report | Sort {$_.SignInDate -as [datetime]} -descending | Out-GridView$Report | Export-CSV -NoTypeInformation $CSVOutputWrite-Host "All done. Report is available in" $CSVOutput
Attribution
Author
Office365itpros