Skip to content

Export Microsoft 365 inactive users report

You want to find all the inactive Microsoft 365 users. There is no benefit to keeping user accounts active when there is no activity. Inactive user accounts become easy targets for hackers, and you should disable these accounts. In this article, you will learn how to export Microsoft 365 inactive users report.

What are Microsoft 365 inactive users

An inactive Microsoft 365 user is when the user hasn’t signed in for the last set of days. This can be different for every organization. Some find that an inactive account is valid when there is no sign-in within the last 60 or 90 days. Some find it’s a 30-day period.

The Center for Internet Security (CIS) recommends to delete or disable any dormant accounts after a period of 45 days of inactivity, where supported.

See 5.3: Disable Dormant Accounts.

Export Microsoft 365 inactive users CIS

Important: You need a Microsoft Entra ID P1 or P2 edition license to view the last sign-in date.

Check user last sign-in date in Microsoft 365 admin center

To check the Microsoft 365 user last sign-in date in Microsoft 365 admin center, follow these steps:

  1. Sign in to Microsoft 365 admin center
  2. Expand Users
  3. Click on Active Users
  4. Select the User
Export Microsoft 365 inactive users admin center
  1. Click on Account > View last 30 days
Export Microsoft 365 inactive users last 30 days
  1. The last sign-in date, status, and failure reason (if available) appear.
Export Microsoft 365 inactive users sign in activity

What if you want to export all the users last sign-in status? PowerShell to the rescue.

Export Microsoft 365 inactive users PowerShell script

The Export-M365InactiveUsers.ps1 PowerShell script will get all the Microsoft 365/Microsoft Entra ID users and export a report to CSV file that shows how many days have elapsed since their last sign-in.

Note: The LastSuccessfulSignInDate value will start to appear in the report within 6 hours. The data for this property isn’t backfilled and starts recording sign-ins after December 1, 2023.

For every user, it gathers the following information:

  1. Id
  2. UserPrincipalName
  3. DisplayName
  4. Email
  5. UserType
  6. AccountEnabled
  7. LastSuccessfulSignInDate
  8. DaysSinceLastSignIn
  9. CreatedDateTime
  10. IsLicensed

Prepare Export-M365InactiveUsers PowerShell script

Create two folders on the (C:) drive:

  • Temp
  • Scripts

Download the Export-M365InactiveUsers.ps1 PowerShell script and place it in C:\scripts folder. The script will export the CSV file to the C:\temp folder.

Ensure the file is unblocked to prevent errors when running the script. Read more in the article Not digitally signed error when running PowerShell script.

Another option is to copy and paste the below code into Notepad. Give it the name Export-M365InactiveUsers.ps1 and place it in the C:\scripts folder.

<#
    .SYNOPSIS
    Export-M365InactiveUsers.ps1

    .DESCRIPTION
    Export Microsoft 365/Microsoft Entra ID inactive users report.

    .LINK
    www.alitajran.com/export-microsoft-365-inactive-users/

    .NOTES
    Written by: ALI TAJRAN
    Website:    www.alitajran.com
    LinkedIn:   linkedin.com/in/alitajran

    .CHANGELOG
    V1.00, 12/13/2023 - Initial version
    V1.10, 02/26/2024 - Added IsLicensed column
    V1.20, 04/02/2024 - Calculate DaysSinceLastSignIn from LastSuccessfulSignInDateTime property
#>

# Export path for CSV file
$CSVPath = "C:\Temp\InactiveUsers.csv"

# Parameters
$InactiveUsers = @()

# Connect to Microsoft Graph API
Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All"

# Get properties
$Properties = @(
    'Id',
    'DisplayName',
    'Mail',
    'UserPrincipalName',
    'UserType',
    'AccountEnabled',
    'SignInActivity',
    'CreatedDateTime',
    'AssignedLicenses'
)

# Get all users along with the properties
$AllUsers = Get-MgBetaUser -All -Property $Properties | Select-Object $Properties

foreach ($User in $AllUsers) {
    $LastSuccessfulSignInDate = if ($User.SignInActivity.LastSuccessfulSignInDateTime) {
        $User.SignInActivity.LastSuccessfulSignInDateTime
    }
    else {
        "Never Signed-in."
    }

    $DaysSinceLastSignIn = if ($User.SignInActivity.LastSuccessfulSignInDateTime) {
        (New-TimeSpan -Start $User.SignInActivity.LastSuccessfulSignInDateTime -End (Get-Date)).Days
    }
    else {
        "N/A"
    }

    # Check if the user is licensed
    $IsLicensed = if ($User.AssignedLicenses) {
        "Yes"
    }
    else {
        "No"
    }

    # Collect data
    if (!$User.SignInActivity.LastSuccessfulSignInDateTime -or (Get-Date $User.SignInActivity.LastSuccessfulSignInDateTime)) {
        $InactiveUsers += [PSCustomObject]@{
            Id                       = $User.Id
            UserPrincipalName        = $User.UserPrincipalName
            DisplayName              = $User.DisplayName
            Email                    = $User.Mail
            UserType                 = $User.UserType
            AccountEnabled           = $User.AccountEnabled
            LastSuccessfulSignInDate = $LastSuccessfulSignInDate
            DaysSinceLastSignIn      = $DaysSinceLastSignIn
            CreatedDateTime          = $User.CreatedDateTime
            IsLicensed               = $IsLicensed
        }
    }
}

# Display data using Out-GridView
$InactiveUsers | Out-GridView -Title "Inactive Users"

# Export data to CSV file
try {
    $InactiveUsers | Export-Csv -Path $CSVPath -NoTypeInformation -Encoding UTF8
    Write-Host "Script completed. Results exported to $CSVPath." -ForegroundColor Cyan
}
catch {
    Write-Host "Error occurred while exporting to CSV: $_" -ForegroundColor Red
}
  • Line 23: Edit CSV file path

Connect to Microsoft Graph PowerShell

Before we can proceed further and get the inactive status for all the users, we need to Install and connect to Microsoft Graph PowerShell.

Start Windows PowerShell as administrator and run the below commands.

Install-Module Microsoft.Graph -Force
Install-Module Microsoft.Graph.Beta -AllowClobber -Force

Important: Always install the Microsoft Graph PowerShell and Microsoft Graph Beta PowerShell modules. That’s because some cmdlets are not yet available in the final version, and they will not work. Update both modules to the latest version before you run a cmdlet or script to prevent errors and incorrect results.

Run the Connect-MgGraph cmdlet.

Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All"

Run Export-M365InactiveUsers PowerShell script

Get all the inactive users with PowerShell. Run the below command to run the script Export-M365InactiveUsers.ps1.

c:\scripts\.\Export-M365InactiveUsers.ps1

Out-GridView

An Out-GridView will show columns with all the inactive users and much more information.

Export Microsoft 365 inactive users Out-GridView

Open Microsoft 365 inactive users report CSV file

The Export-M365InactiveUsers.ps1 PowerShell script will export Microsft 365 users inactivity to CSV file. Find the file InactiveUsers.csv in the path C:\temp.

Temp folder with CSV file output

Open the CSV file with your favorite application. In our example, it’s Microsoft Excel.

CSV file

Did this help you to export Microsoft 365 inactive users to CSV file?

Note: Do you want to understand all three SignIn properties and how to retrieve them? Read the article Export Microsoft 365 users last sign-in date and time.

Read more: Block sign-in from shared mailboxes »

Conclusion

You learned how to export inactive users from Microsoft 365. Get the inactive users report with Export-M365InactiveUsers PowerShell script and carefully review it. Check why there is no user sign-in activity and disable the inactive user accounts to protect your organization.

Did you enjoy this article? You may also like Export Azure AD users to CSV with PowerShell. Don’t forget to follow us and share this article.

ALI TAJRAN

ALI TAJRAN

ALI TAJRAN is a passionate IT Architect, IT Consultant, and Microsoft Certified Trainer. He started Information Technology at a very young age, and his goal is to teach and inspire others. Read more »

This Post Has 12 Comments

  1. Thanks for the information!

    Is there any way to exclude non-interactive sign-ins for LastSuccessfulSignInDateTime? I just want to know the last time someone successfully logged in with their username and password and am having a surprisingly difficult time getting this data through a script.

    1. The exported CSV file shows the column “UserType”. You can filter it on “Guest”.

      If you only want to search for guest accounts, you must replace:

      $AllUsers = Get-MgBetaUser -All -Property $Properties | Select-Object $Properties

      To:

      $AllUsers = Get-MgBetaUser -All -Filter "userType eq 'Guest'" -ConsistencyLevel eventual -CountVariable CountVar -Property $Properties | Select-Object $Properties

      Read more in the article How to use Get-MgUser in PowerShell.

  2. Great article. However, one thing I noticed is you use LastSuccessfulSignInDateTime to determine the date, but then use LastSignInDateTime to calculate the number of days since last sign in. Those are not the same properties, so you can have a user that shows LastSuccessfulSignInDateTime a month ago, however number of days since last sign in shows like 200 days. I believe LastSignInDateTime shows last interactive sign in (there’s also LastNonInteractiveSignInDateTime) and I think LastSuccessfulSignInDateTime shows the last successful sign-in, regardless if it was interactive or not. Can you confirm? If so, wouldn’t it be best to also use LastSuccessfulSignInDateTime when calculating $DaysSinceLastSignIn?

    1. You’re correct. I forgot to update that part in the script when I changed it to the new LastSuccessfulSignInDateTime property that was introduced.

      I updated the script. The DaysSinceLastSignIn will calculate the days from the LastSuccessfulSignInDateTime property.

      Thanks for letting me know. I appreciate your comment.

      Confirmed, the LastSuccessfulSignInDateTime shows the last successful sign-in, regardless if it was interactive or not.

      Yes, there are three sign-in properties that you can retrieve. But you need a Microsoft Entra ID P1/P2 license. If you use Microsoft Entra ID Free, it will only show the last 7 days and it’s not available using PowerShell.

      Everything is explained in the article Export Microsoft 365 users last sign-in date and time.

  3. Hello, and thank you for the script. My manager wants me to deactivate stale accounts. I’ve installed the graph and graph beta modules as indicated. Using “Get-MgBetaUser” on line 44 results in an error, and when I change it to “Get-MgUser” the CSV output shows all users as “Never Signed-in.” including myself. Is there something I can do?

    1. Hi Kurt,

      You really need to call the “Get-MgBetaUser” cmdlet to retrieve the correct information. That’s because the “LastSuccessfulSignInDateTime” property has not yet been ported to the stable version.

      If you’re using the “Get-MgUser” cmdlet, you will see “Never Signed-in” for all the users, as you mentioned.

      It looks like something is wrong with your Microsoft Graph Beta module. Which version are you running? The latest version is 2.16.0. Try uninstalling the module and installing it again.

      Everything is explained in the article Install Microsoft Graph PowerShell module.

      1. Good morning, Ali. Thank you for the advice – it worked. Fully uninstalling all of MGraph and MGraphBeta was a long and difficult chore, but after a fully clean uninstall, then a reinstall of both modules as you describe above, the script works. My management is very pleased, thanks again.

  4. Great article!

    This begs the question, how does one mass-disable all “inactive users” found in the above output?

    How does this approach capture the differences in login times in a hybrid environment where a user might not ever log into cloud or vice versa so the user seems stale in one platform but not in another?

    I appreciate any feedback and maybe this is part of an upcoming article?

Leave a Reply

Your email address will not be published. Required fields are marked *