Back to script library
Entra / Microsoft 365 · Users & guests

Get user sign-in data (Graph)

A script to fetch user sign-in data from the Microsoft Graph.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

# Review required modules and connection steps before running.
# Connect to Microsoft Graph or Exchange Online as needed for this script.

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

Clear-Host
# Get User sign in data
Write-Host "Accessing the Graph to get user sign-in data..."
$URI = "https://graph.microsoft.com/beta/users?`$select=displayName,userPrincipalName, mail, id, CreatedDateTime, signInActivity, UserType&`$top=100"
[array]$SignInData = (Invoke-RestMethod -Uri $URI -Headers $Headers -Method Get -ContentType "application/json")
If ($SignInData.Value.count) {
$SignInData = $SignInData.Value
}
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($User in $SignInData) {
[string]$LastSignInOutput = $Null
If ($Null -ne $User.SignInActivity) {
$LastUserSignInDate = $User.SignInActivity['lastSignInDateTime']
If ($Null -ne $LastUserSignInDate) {
$LastSignInOutput = Get-Date($LastUserSignInDate) -format g
$DaysSinceSignIn = (New-TimeSpan $LastUserSignInDate).Days
}
} Else { #No sign in data for this user account
$LastSignInOutput = "Never or > 180 days"
$DaysSinceSignIn = "N/A"
}
$ReportLine = [PSCustomObject] @{
UPN = $User.UserPrincipalName
DisplayName = $User.DisplayName
Email = $User.Mail
ObjectId = $User.Id
Created = Get-Date($User.CreatedDateTime) -format g
LastSignIn = $LastSignInOutput
DaysSinceSignIn = $DaysSinceSignIn
UserType = $User.UserType }
$Report.Add($ReportLine)
} # End ForEach
# Do we have extra data to fetch?
$NextLink = $SignInData.'@Odata.NextLink'
While ($Null -ne $NextLink) { # We do... so process them.
Write-Host "Still processing..."
$SignInData = Invoke-WebRequest -Method GET -Uri $NextLink -ContentType "application/json" -Headers $Headers
$SignInData = $SignInData | ConvertFrom-JSon
ForEach ($User in $SignInData.Value) {
[string]$LastSignInOutput = $Null
If ($Null -ne $User.SignInActivity) {
$LastUserSignInDate = $User.SignInActivity.LastSignInDateTime
If ($Null -ne $LastUserSignInDate) {
$LastSignInOutput = Get-Date($LastUserSignInDate) -format g
$DaysSinceSignIn = (New-TimeSpan $LastUserSignInDate).Days
}
} Else { #No sign in data for this user account
$LastSignInOutput = "Never or > 180 days"
$DaysSinceSignIn = "N/A"
}
$ReportLine = [PSCustomObject] @{
UPN = $User.UserPrincipalName
DisplayName = $User.DisplayName
Email = $User.Mail
ObjectId = $User.Id
Created = Get-Date($User.CreatedDateTime) -format g
LastSignIn = $LastSignInOutput
DaysSinceSignIn = $DaysSinceSignIn
UserType = $User.UserType }
$Report.Add($ReportLine) }
# Check for more data
$NextLink = $SignInData.'@Odata.NextLink'
} # End While
Write-Host "All done. " $Report.Count "accounts processed - output available in c:\Temp\ReportUserSignin.csv."
$Report | Sort-Object DisplayName | Out-GridView
$Report | Export-CSV -NoTypeInformation c:\Temp\ReportUserSignin.csv
Attribution