Find a Users Last Sign-In (across Interactive & Non-Interactive) with Microsoft Graph PowerShell

Learn how to retrieve each users most recent sign-in by combining interactive and non-interactive timestamps (signInActivity) in Microsoft Entra ID with Microsoft Graph PowerShell.

# Validated on Microsoft.Graph PowerShell SDK v2.29.1
$ErrorActionPreference = 'Stop'

$ctx = $null
try { $ctx = Get-MgContext -ErrorAction Stop } catch {}

$scopes = @()
if ($ctx) { $scopes = $ctx.Scopes }

$hasUserScope = $scopes -contains 'User.ReadWrite.All' -or $scopes -contains 'User.Read.All' # preferred
$hasAuditScope = $scopes -contains 'AuditLog.Read.All'

if (-not $ctx -or -not $hasUserScope -or -not $hasAuditScope) {
    Connect-MgGraph -Scopes @('User.Read.All', 'AuditLog.Read.All') -NoWelcome
}

function Get-MgUserLastSignIn {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$UserPrincipalName
    )

    $select = 'signInActivity, userPrincipalName, displayName'
    $params = @{ 
        'All'              = $true
        'Filter'           = "userPrincipalName eq '$UserPrincipalName'"
        'ConsistencyLevel' = 'eventual'
        'CountVariable'    = 'userCount'
        'Select'           = $select
    }

    $user = Get-MgUser @params

    if (-not $user.SignInActivity) {
        return [pscustomobject]@{
            DisplayName       = $user.DisplayName
            UserPrincipalName = $user.UserPrincipalName
            LastSignIn        = $null
        }
    }

    $lastSignIn = @(
        $user.SignInActivity.lastSignInDateTime,
        $user.SignInActivity.lastNonInteractiveSignInDateTime
    ) | Sort-Object -Descending | Select-Object -First 1

    [pscustomobject]@{
        DisplayName       = $user.DisplayName
        UserPrincipalName = $user.UserPrincipalName
        LastSignIn        = $lastSignIn
    }
}

# Get-MgUserLastSignIn -UserPrincipalName "user@domain.com"
Loading...