In today’s digital workplace, managing user accounts efficiently is essential for maintaining a secure and organized environment. Identifying and handling inactive user accounts in Office 365 is crucial to this process.
Inactive accounts pose security risks and can clutter your system, waste precious licenses, and impact overall productivity.
In this blog post, we will explore various methods to identify and manage inactive users in Office 365 using different ways.
Table of Contents
What is Considered an Inactive User?
There are generally two criteria to identify Office 365 inactive users.
- The user account hasn’t signed in within a specified period.
- The user account had no recorded activities in Exchange Online, SharePoint Online, Yammer, Teams, and OneDrive, within a specified period.
Administrators can consider one or both criteria when analyzing inactive Office 365 users for possible clean-up and freeing up of unused licenses.
The period by which the accounts are considered inactive is subjective. It could be the last 30 days, 90 days, etc. The organization or administrators must be the ones to nominate the optimal period of inactivity.
Find Inactive Users in Office 365 using Microsoft Entra Admin Center by the Last Login Date
The Microsoft Enter Admin Center (formerly Azure Active Directory Admin Center) provides a user-friendly interface to manage user accounts and activities. To find inactive users based on their last login date, follow these steps:
- Log in to Microsoft Entra and navigate to Identity → Users → All Users.
- Click Manage view → Edit columns.
- Customize the columns, ensure the “Last sign-in time” column is visible, and click Save.
- Click Add filter and select the “Last sign-in time” column.
- Change the Operator to “<=” (less than or equal to), specify the Value (date) threshold, and click Apply. This filter only shows accounts that last signed in on or before the selected date.
- You now have a list of inactive Office 365 users who have not signed in to their accounts within the previous number of days. Click “Download users”, enter the filename to generate the Office 365 inactive users report CSV file, and click Start.
- Click the “Bulk operation results” menu blade and select the report from the list. Note that the status should be “Completed” before downloading the report.
- Click the “Download results” link, specify the filename and location, and click Save.
You’ve now downloaded the Office 365 Inactive users report.
Find Inactive Users in Office 365 using Microsoft 365 Admin Center by the Last Activity Date
Before you proceed with this method, follow the “Microsoft 365 reports show anonymous user names instead of actual user names” instructions to ensure that the Microsoft 365 report shows the user names.
Like the previous method, you can find inactive users based on their last activity date. The data can be found in the usage reports. Here’s how:
- Log in to the Microsoft 365 Admin Center.
- Navigate to Reports → Usage → Microsoft 365 apps → Active Users. Select the reporting period, such as “Past 90 days”. Doing so will show the activity logs in the past 90 days.
- Here you can find out which users have licenses assigned but had no activities within the specified reporting period.
- You can also export this report by clicking the Export button and downloading the resulting CSV file.
Generate Office 365 Inactive Users Report using Microsoft Graph PowerShell by the Last Login Date
This method requires installing the latest Microsoft Graph PowerShell v1.0 module on your computer. Refer to this Microsoft Document.
For those who prefer a more automated approach, Microsoft Graph PowerShell can be a powerful tool. This method lets you generate detailed reports on inactive users based on their last login date. Here’s how:
- First, copy the script below and save it to your computer as Get-InactiveUsersByLastLogInDate.ps1. You can also download the code from this link.
# Get-InactiveUsersByLastLogInDate.ps1 [CmdletBinding()] param ( [Parameter(Mandatory)] [int] $DaysWithoutLogIn ) # Convert the date to datetimeoffset "yyyy-MM-ddThh:mm:ssZ" format. $OnOrBefore = ((Get-Date).AddDays(-$DaysWithoutLogIn)).ToString("yyyy-MM-ddT00:00:00Z") # Compose the API filter. $filter = ('signInActivity/LastSignInDateTime le ' + $($OnOrBefore)) try { # Import the required module Import-Module Microsoft.Graph.Users # Get users and Get-MgUser -All -Filter $filter -ErrorAction Stop -Property ` 'DisplayName', 'UserPrincipalName', 'Mail', 'UserType', 'AccountEnabled', 'SignInActivity' | Select-Object 'DisplayName', 'UserPrincipalName', 'Mail', 'UserType', 'AccountEnabled', @{n = 'LastLoginDate'; e = { $( if (!$_.SignInActivity.LastSignInDateTime) { # If no LastSignInDateTime value, set it to the oldest datetime. [datetime]::MinValue } else { $_.SignInActivity.LastSignInDateTime } ) } }, @{n = 'DaysWithoutLogIn'; e = { $( if (!$_.SignInActivity.LastSignInDateTime) { # If no LastSignInDateTime value, set it to the oldest datetime. (New-TimeSpan -Start ([datetime]::MinValue)).Days } else { (New-TimeSpan -Start ($_.SignInActivity.LastSignInDateTime)).Days } ) } } } catch { $_.Exception.Message | Out-Default return $null }
- Open PowerShell and change the working directory to where you saved the script.
Set-Location <script location>
- Run the following command to connect to Microsoft Graph. This connection explicitly requests the AuditLog.Read.All and User.Read.All API permissions.
Import-Module Microsoft.Graph.Beta.Authentication Connect-MgGraph -Scopes "AuditLog.Read.All", "User.Read.All" -TenantId <tenant ID>
- Click “Accept” to consent to the requested permissions.
- Execute the script as shown below. Adjust the -DaysWithoutLogIn value as needed.
.\Get-InactiveUsersByLastLogInDate.ps1 -DaysWithoutLogIn 30 | Sort-Object LastLoginDate
This example will find inactive users in Office 365 without any login record in the past 30 days sorted by LastLoginDate.
You can also export the results to a CSV file by piping it to the Export-Csv cmdlet..\Get-InactiveUsersByLastLogInDate.ps1 -DaysWithoutLogIn 30 | Export-Csv <csv file> -NoTypeInformation
Generate Office 365 Inactive Users Report using Microsoft Graph PowerShell by the Last Activity Date
Similar to the previous method, you can generate an inactive Office 365 users report based on the last activity date.
Users assigned licenses, such as Exchange, SharePoint, Teams, OneDrive for Business, and Yammer, are expected to use those services. If not, it would be best to know who isn’t using their Office 365 services.
- Copy the script below and save it to your computer with the filename Get-InactiveUsersByLastActivityDate.ps1. You can also download the script from this link.
#Get-InactiveUsersByLastActivityDate.ps1 [CmdletBinding()] param ( [Parameter(Mandatory)] [int] $DaysWithoutActivity ) try { Import-Module Microsoft.Graph.Reports $tempCsv = "$env:temp\tmp_office365users.csv" Get-MgReportOffice365ActiveUserDetail -Period D180 -OutFile $tempCsv -ErrorAction Stop -WarningAction SilentlyContinue $data = Import-Csv -Path $tempCsv } catch { $_.Exception.Message | Out-Default return $null } try { $data | ForEach-Object { [System.Collections.ArrayList]$inactiveDays = @() if ($_.'Has Exchange License' -eq 'TRUE') { if ($_.'Exchange Last Activity Date') { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'Exchange Last Activity Date')).Days)) } else { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'Exchange License Assign Date')).Days)) } } else { $null = $inactiveDays.Add(0) } if ($_.'Has SharePoint License' -eq 'TRUE') { if ($_.'SharePoint Last Activity Date') { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'SharePoint Last Activity Date')).Days)) } else { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'SharePoint License Assign Date')).Days)) } } else { $null = $inactiveDays.Add(0) } if ($_.'Has OneDrive License' -eq 'TRUE') { if ($_.'OneDrive Last Activity Date') { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'OneDrive Last Activity Date')).Days)) } else { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'OneDrive License Assign Date')).Days)) } } else { $null = $inactiveDays.Add(0) } if ($_.'Has Teams License' -eq 'TRUE') { if ($_.'Teams Last Activity Date') { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'Teams Last Activity Date')).Days)) } else { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'Teams License Assign Date')).Days)) } } else { $null = $inactiveDays.Add(0) } if ($_.'Has Yammer License' -eq 'TRUE') { if ($_.'Yammer Last Activity Date') { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'Yammer Last Activity Date')).Days)) } else { $null = $inactiveDays.Add($((New-TimeSpan -Start (Get-Date $_.'Yammer License Assign Date')).Days)) } } else { $null = $inactiveDays.Add(0) } $DaysInactive = ($inactiveDays | Sort-Object)[0] # $DaysInactive | Out-Default if ($DaysInactive -ge $DaysWithoutActivity) { [PSCustomObject]@{ Name = $_.'Display Name' Username = $_.'User Principal Name' DaysWithoutActivity = $DaysInactive } } } } catch { $_.Exception.Message | Out-Default }
- Open PowerShell and change the working directory to where you saved the script.
Set-Location <script location>
- Run the following command to connect to Microsoft Graph. This connection explicitly requests the Reports.Read.All API permission.
Import-Module Microsoft.Graph.Beta.Authentication Connect-MgGraph -Scopes "Reports.Read.All" -TenantId <tenant ID>
- Click “Accept” to consent to the requested permissions.
- Execute the script as shown below. Adjust the -DaysWithoutActivity value as needed.
.\Get-InactiveUsersByLastActivityDate.ps1 -DaysWithoutActivity 30
This example will find inactive users in Office 365 whose last activity in Exchange, Teams, OneDrive, SharePoint, and Yammer is beyond the past 30 days.
You can also export the results to a CSV file by piping it to the Export-Csv cmdlet..\Get-InactiveUsersByLastActivityDate.ps1 -DaysWithoutActivity 30 | Export-Csv <csv file> -NoTypeInformation
Conclusion
Microsoft 365 inactive users take up licenses that can otherwise be assigned to another who can fully utilize it. Even so, if the user hasn’t logged in to their account in a long time, those accounts are stale and can pose a security risk to the organization.
Knowing how to generate O365 inactive user reports benefits administrators and the organization. They’ll be ahead in maintaining active user accounts and have the additional data source to analyze inactive users and take appropriate housekeeping actions.