Skip to content

/commands/entra-id/get-last-sign-in-date-users

Get the last sign-in date of Microsoft Entra ID users with PowerShell (signInActivity)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
Microsoft Entra ID
versions
Microsoft.Graph.Users 2.41.2
os
windows, linux, macos

The last sign-in time of Microsoft Entra ID users is the signInActivity property of the user object. With the Microsoft Graph PowerShell SDK, connect with AuditLog.Read.All and User.Read.All, and request the property explicitly with Get-MgUser -Property; it is not returned by default:

powershell
Connect-MgGraph -Scopes 'AuditLog.Read.All', 'User.Read.All'
Get-MgUser -All -Property Id, UserPrincipalName, AccountEnabled, SignInActivity |
  Select-Object UserPrincipalName, AccountEnabled,
    @{n='LastSuccessful'; e={$_.SignInActivity.LastSuccessfulSignInDateTime}},
    @{n='LastInteractive'; e={$_.SignInActivity.LastSignInDateTime}},
    @{n='LastNonInteractive'; e={$_.SignInActivity.LastNonInteractiveSignInDateTime}} |
  Sort-Object LastSuccessful

Reading lastSuccessfulSignInDateTime needs a Microsoft Entra ID P1 or P2 license, and Reports Reader is the least privileged role for delegated access. Timestamps are in UTC.

The properties

The block reads the SignInActivity model from Microsoft.Graph.Users 2.41.2 and asks the SDK's offline permission catalog which permission the property needs:

powershell
Import-Module Microsoft.Graph.Users
[Microsoft.Graph.PowerShell.Models.MicrosoftGraphSignInActivity].GetProperties() |
  Where-Object Name -like '*DateTime' | ForEach-Object { $_.Name }
Find-MgGraphPermission -SearchString AuditLog.Read.All -ExactMatch |
  ForEach-Object { '{0} ({1})' -f $_.Name, $_.PermissionType }

Output

LastNonInteractiveSignInDateTime
LastSignInDateTime
LastSuccessfulSignInDateTime
AuditLog.Read.All (Delegated)
AuditLog.Read.All (Application)
PropertyWhat it records
LastSuccessfulSignInDateTimeLast successful sign-in, interactive or not; best for inactivity reports (from December 2023, not backfilled)
LastSignInDateTimeLast interactive attempt, including failed ones
LastNonInteractiveSignInDateTimeLast attempt by a client signing in on the user behalf, successful or not; kept since May 2020

A blank value means the account never signed in, or its last sign-in was before April 2020.

Find users inactive for 90 days

Filter on the server instead of downloading every user:

powershell
$cutoff = (Get-Date).ToUniversalTime().AddDays(-90).ToString('yyyy-MM-ddTHH:mm:ssZ')
Get-MgUser -All -Filter "signInActivity/lastSuccessfulSignInDateTime le $cutoff" `
  -Property UserPrincipalName, AccountEnabled, SignInActivity |
  Select-Object UserPrincipalName, AccountEnabled, @{n='Last'; e={$_.SignInActivity.LastSuccessfulSignInDateTime}}

The signInActivity filter supports eq, ne, not, ge and le, but cannot be combined with other filterable properties in the same -Filter; filter the rest in PowerShell with Where-Object. Users that never signed in have no value and are not matched by le, so list them separately with Where-Object { -not $_.SignInActivity.LastSuccessfulSignInDateTime } on a full export. Microsoft suggests 90 to 180 days as a common window.

Pitfalls

  • A property missing from -Property is empty in the output even when it has a value, a common reason for "no data" reports; see the -Property and -ConsistencyLevel notes.
  • The Graph permissions are not enough on their own: lastSuccessfulSignInDateTime also needs a P1 or P2 license in the tenant.
  • The value can lag up to 24 hours behind the sign-in logs.
  • For on-premises accounts, the equivalent is lastLogonTimestamp in Active Directory; see Search-ADAccount -AccountInactive.

Once you have the list, block the accounts with Update-MgUser -AccountEnabled:$false before deleting them.

FAQ

Why is SignInActivity empty in Get-MgUser output?

It is not returned by default. Name it in -Property, and connect with AuditLog.Read.All as well as User.Read.All. The tenant also needs Microsoft Entra ID P1 or P2.

What is the difference between lastSignInDateTime and lastSuccessfulSignInDateTime?

lastSignInDateTime is the last interactive attempt, failed ones included. lastSuccessfulSignInDateTime is the last successful sign-in, interactive or not, and is the one to use for inactive-account reports. It exists since December 2023 and was not backfilled.

How current is the value?

Microsoft says the last sign-in on the user object can take up to 24 hours to update. Use the sign-in logs when you need near real-time data.

Sources