Finding Inactive Microsoft 365 Users with PowerShell and Microsoft Graph
Every Microsoft 365 tenant collects accounts nobody uses anymore. A contractor finishes a project, a temp leaves after a busy season, or someone sets up a test account and forgets it exists. Each of those accounts is a problem twice over. It is a security risk, because an account nobody watches is an ideal target for a password spray or phishing attack. It is often a cost too, because many of…
Every Microsoft 365 tenant holds accounts that are no longer in use. These accounts can pose two problems: they are vulnerable to security threats and they unnecessarily consume licensing costs. The Microsoft 365 admin centre only shows sign-in activity for one user at a time, which makes it difficult to identify inactive accounts on a large scale. To address this issue, a PowerShell script has been developed that utilizes the Microsoft Graph PowerShell SDK to find all inactive accounts in one go.
Before executing the script, certain prerequisites need to be met. The Microsoft Graph PowerShell SDK must be installed on the machine, and the tenant must have Microsoft Entra ID P1 or P2 licenses. The required permissions are User.Read.All and AuditLog.Read.All, which necessitate admin consent upon the first connection. If the SDK is not yet installed, it can be added using the command: Install-Module Microsoft.Graph -Scope CurrentUser.
The script starts by connecting to Microsoft Graph with the necessary permissions. It then defines the cutoff date, which is 90 days prior to the current date. The script retrieves every user in the tenant along with their properties, including ID, display name, user principal name, user type, account status, creation date, assigned licenses, and sign-in activity. It filters for member accounts, as guest accounts are handled separately.
The script proceeds to create a report of inactive users. For each user, it identifies the most recent sign-in, whether interactive or non-interactive. Accounts created recently without any sign-in activity are skipped. The script also checks if the user has logged in within the cutoff period. If not, the user is added to the report with details such as display name, user principal name, account status, licensing status, creation date, and last sign-in date.
Once the report is generated, it is exported as a CSV file and a summary is displayed. The report shows the total number of inactive accounts found, as well as how many of those still have active licenses. It's important to note that accounts with no license are primarily a security concern, while those with licensed accounts represent an opportunity for cost savings.
The script is designed to provide a comprehensive overview of inactive accounts, allowing businesses to prioritize their cleanup efforts and potentially reduce unnecessary costs. However, it is recommended to review the report before taking any action, as some inactive accounts may have legitimate purposes or belong to individuals on extended leave. A safer approach would be to first disable the account to eliminate any immediate security risk.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.