Share via

sigin logs for the users.

Glenn Maxwell 13,761 Reputation points
2026-06-19T06:23:55.19+00:00

Hi All,

I have a test environment with approximately 200 Microsoft 365 E5 licenses and Microsoft Copilot licenses.

Our environment is Exchange Hybrid. Users are created as remote mailboxes on-premises or are created on-premises and later migrated to Exchange Online. Licensing is assigned through group-based licensing, where users are added to an on-premises Active Directory group that syncs to Entra ID, and licenses are assigned based on group membership.

I frequently receive requests to assign E5 and Copilot licenses. Since the number of available licenses is limited, I currently review user sign-in activity manually in Entra ID and identify users who have not signed in during the last 30 days. I then remove those users from the licensing group and reassign the licenses to new users.

At present, I check both:

  • User Sign-ins (Interactive)
  • User Sign-ins (Non-Interactive)

My requirements are:

  1. Import users from csv file(i have the users list in csv file, exported from onprem AD group)
  2. Obtain their last Interactive Sign-in date from Entraid.
  3. Obtain their last Non-Interactive Sign-in date from Entraid.
  4. Include the user creation date (or account creation date) in the output.
  5. Export the results to a CSV file.
  6. Identify users who have not signed in during the last 30 days so that their licenses can be reclaimed.

What would be the best approach using Microsoft Graph PowerShell or Entra PowerShell?

If anyone has a PowerShell script or example that can retrieve this information and export it to CSV, I would appreciate your guidance.

Microsoft Security | Microsoft Entra | Microsoft Entra ID

1 answer

Sort by: Most helpful
  1. AI answer

    2026-06-19T06:24:19.7833333+00:00

    Use Microsoft Graph PowerShell to pull sign-in activity and account properties, then filter and export. Entra PowerShell also exposes sign-in activity per user, but Graph is better suited for bulk/reporting.

    Below is an outline that matches the requirements, using the patterns from the documented examples.

    1. Prerequisites

    1. Install and import Microsoft Graph PowerShell:
         Install-Module Microsoft.Graph -Scope CurrentUser
         Import-Module Microsoft.Graph
      
    2. Connect with the right permissions (audit + users):
         Connect-MgGraph -Scopes "AuditLog.Read.All","User.Read.All"
      

    2. Input: users from CSV

    Assume the CSV from on-prem AD group has a column UserPrincipalName (adjust if different):

    $users = Import-Csv -Path "C:\temp\groupUsers.csv"
    

    3. Get last sign-in activity per user

    The documented Entra PowerShell example shows how to retrieve sign-in activity for a single user and expand the SignInActivity property:

    Connect-Entra -Scopes 'User.Read.All','AuditLog.Read.All'
    Get-EntraUser -UserId '******@contoso.com' -Property 'SignInActivity' | 
      Select-Object -Property Id, DisplayName, UserPrincipalName -ExpandProperty 'SignInActivity'
    

    Using the same pattern, loop through the CSV list and collect:

    • Last interactive sign-in
    • Last non-interactive sign-in
    • Account creation date

    Example using Entra PowerShell cmdlets:

    Connect-Entra -Scopes 'User.Read.All','AuditLog.Read.All'
    
    $results = foreach ($u in $users) {
        $upn = $u.UserPrincipalName
    
        # Get user with sign-in activity and creation date
        $user = Get-EntraUser -UserId $upn -Property 'SignInActivity','CreatedDateTime'
    
        if (-not $user) { continue }
    
        $signIn = $user.SignInActivity
    
        [PSCustomObject]@{
            Id                          = $user.Id
            DisplayName                 = $user.DisplayName
            UserPrincipalName           = $user.UserPrincipalName
            CreatedDateTime             = $user.CreatedDateTime
            LastInteractiveSignInDate   = $signIn.LastSignInDateTime
            LastNonInteractiveSignInDate= $signIn.LastNonInteractiveSignInDateTime
        }
    }
    

    This follows the documented pattern of expanding SignInActivity and selecting user properties.

    4. Filter users inactive for 30 days

    Once the data is in $results, calculate inactivity based on the most recent sign-in (interactive or non-interactive):

    $cutoff = (Get-Date).AddDays(-30)
    
    $resultsWithCalc = $results | ForEach-Object {
        $lastInteractive   = $_.LastInteractiveSignInDate
        $lastNonInteractive= $_.LastNonInteractiveSignInDate
    
        # Determine the most recent sign-in of any type
        $lastAny = $lastInteractive
        if ($lastNonInteractive -and (!$lastAny -or $lastNonInteractive -gt $lastAny)) {
            $lastAny = $lastNonInteractive
        }
    
        $_ | Add-Member -NotePropertyName LastAnySignInDate -NotePropertyValue $lastAny -Force
        $_
    }
    
    $inactive30Days = $resultsWithCalc | Where-Object {
        -not $_.LastAnySignInDate -or $_.LastAnySignInDate -lt $cutoff
    }
    

    $inactive30Days now contains users who have not signed in (interactive or non-interactive) in the last 30 days and are candidates for license reclamation.

    5. Export to CSV

    Export both the full dataset and the inactive subset:

    $resultsWithCalc | Export-Csv -Path "C:\temp\AllUsersSignInReport.csv" -NoTypeInformation -Encoding UTF8
    $inactive30Days  | Export-Csv -Path "C:\temp\InactiveOver30Days.csv" -NoTypeInformation -Encoding UTF8
    

    6. Optional: use audit logs for deeper analysis

    If more detailed sign-in history is needed (for example, to validate specific events), audit and sign-in logs can be queried with Microsoft Graph PowerShell. The monitoring and health documentation shows how to query audit logs using Get-MgAuditLogDirectoryAudit with filters such as category and activity date:

    Get-MgAuditLogDirectoryAudit -Filter "activityDateTime gt 2019-04-18"
    

    Similar approaches can be used for sign-in logs when more granular analysis is required.

    This approach satisfies:

    1. Import users from CSV.
    2. Retrieve last interactive and non-interactive sign-in dates via SignInActivity.
    3. Include account creation date (CreatedDateTime).
    4. Export to CSV.
    5. Identify users inactive for 30 days for license reclamation.

    References:

    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.