Updated 20 hours ago

Find Unused Licenses in Microsoft 365 Using PowerShell

by Blesslin Rinu

6 min read

No Comments

When users leave the organization, switch to new roles, or become inactive, their Microsoft 365 licenses often remain assigned unnecessarily. These unused licenses not only increase your subscription costs but also create unnecessary security risks if left unmanaged. 😕

That’s why finding inactive licenses is crucial. Since Microsoft 365 doesn’t provide a direct way to track them, reviewing users’ sign-in activity is a reliable approach. In this blog, we’ll show different ways to identify inactive licenses in Microsoft 365, so you can reduce costs and keep your tenant secure.

How to Check Unused Licenses in Microsoft 365

Here are some practical methods you can use to manage unused licenses:

Microsoft Entra admin center: In the Users section, see which licenses are assigned to each user and check their last sign-in activity. This can help you spot licenses tied to accounts that haven’t been used in a while. While this works for a few users, in a large organization it becomes tedious, as you have to switch tabs and analyse accounts one by one.

PowerShell: You can use cmdlets like Get-MgUser to retrieve license details along with the last sign in activity. The drawback is that manually combining, filtering, and analysing these results is complex and error-prone.

To overcome these challenges and simplify Microsoft 365 license management, we have built a custom PowerShell script to clean up unused licenses. The script checks both direct and group-based license assignments, fetches the last successful sign-in details, calculates inactive days, and generates clean, ready-to-use reports in one go.

Download Script: FindUnusedM365Licenses.zip

Script Highlights

  • Retrieves unused licenses based on users’ last successful sign-in time.
  • Lists licenses assigned to sign-in disabled users.
  • Identifies licenses assigned to never logged-in user accounts.
  • Filters unused licenses by type, such as paid, free, or trial.
  • Fetches inactive licenses assigned to external accounts.
  • Identifies unused specific licenses, such as Power BI Pro.
  • Automatically verifies and installs the Microsoft Graph PowerShell Module (if not already installed) upon your confirmation.
  • Supports Certificate-based Authentication (CBA) too.
  • The script is scheduler-friendly.

Find Unused Licenses in Microsoft 365: Sample Output

Here’s how the exported inactive license report appears:

find-unused-licenses-sample-output

The report includes attributes such as display name, UPN, user type, account status, license plans, directly assigned licenses, license assigned via groups, assigned via (group name), license count, last successful sign-in date, inactive days, last interactive sign-in date, last non-interactive sign-in date, creation date, department and job title. This offers complete visibility into both direct and group-based license assignments, making it easier to identify and reclaim unused licenses.

Audit Unused Microsoft 365 Licenses – Script Execution Steps

Follow the steps below to run the script and generate your unused license report:

  1. Download the script.
  2. Start the Windows PowerShell.
  3. Select any of the methods provided to execute the script.

Method 1: Execute the script with MFA or non-MFA accounts

This method allows you to run the script interactively. It retrieves users’ last successful sign-in activity and exports the results to a CSV file, making it easier to track inactive accounts. Regular monitoring helps avoid unused or duplicate license assignments across your organization.

Method 2: Run the script using certificate-based authentication.

To run the script unattended, you can register an app in Microsoft Entra that helps you connect to Graph using certificate. While configuring the app, make sure to grant the API permissions to the app, such as User.Read.All, Group.Read.All, Organization.Read.All, AuditLog.Read.All.

You can either use a CA certificate or create a self-signed certificate, which is cost-effective. Since the script is scheduler-friendly, you can automate it with Task Scheduler or Azure Automation to run at regular intervals. This ensures unused licenses are continuously detected and reclaimed without manual effort.

Get the Best Out of This Script!

The script comes with built-in filters that make it highly flexible for different scenarios. You can customize the output based on your requirements and focus only on the licenses you want to track. Here are some practical use cases:

  1. Filter unused license report to specific plan
  2. CSV import to identify unused subscriptions
  3. Audit unused licenses for never logged in accounts
  4. Track unused licenses assigned to internal users
  5. Identify inactive licenses assigned to external users
  6. Analyse unused licenses for sign-in enabled users
  7. Track unused licenses for sign-in disabled users
  8. Spot unused free Microsoft 365 subscriptions
  9. Find inactive paid Microsoft 365 subscriptions
  10. Reclaim inactive trial Microsoft 365 subscriptions

1. Filter Unused License Report to Specific Plan

By default, the script generates a report of all unused licenses across your tenant. However, in many cases you may want to focus on specific license plans. For instance, if a particular group of users is under review or a certain license plan is consuming too many unused seats, the report can be filtered to include only that plan.

To filter the results for a single license plan, use the -LicensePlanList parameter:

Replace <LicensePlan> with the license plan name (SKU part number), for example “POWER_BI_PRO” to check all unused Power BI licenses.

⚠️Important: The -LicensePlanList parameter only accepts license SKU part numbers and not license friendly names (e.g., Office 365 E3).

2. CSV Import to Identify Unused Subscriptions

In large organizations with several Microsoft 365 plans, tracking unused licenses individually can be tedious. To streamline this, the script supports bulk execution through a CSV input file.

First, create a CSV file that lists the license plan names you want to audit. The file should be formatted as shown below:

license-plan-names-csv-file

Once the CSV file is ready, run the script and provide the file path using the -ImportCSVPath parameter:

Replace <FilePath> with the actual location of your CSV file. The script will then generate unused license reports only for the specified license plans, saving your time and effort.

3. Audit Unused Licenses for Never Logged-In Accounts

As an admin, you must make sure every license is actively used. Some accounts are assigned licenses but remain inactive without ever logging in. These include test accounts, inactivated onboarding accounts, or accidentally provisioned temporary users. Such never-logged-in accounts consume licenses, increase costs, and create security risks.

You can find them by running the script with the -ReturnNeverLoggedInUser parameter as shown below:

This report helps you find unused licenses of accounts that never logged in, lowers security risks, and ensures better control over license allocation.

4. Track Unused Licenses Assigned to Internal Users

When employees change roles or leave, their licenses often remain assigned, leading to unnecessary expenses and security concerns. To track unused licenses assigned to internal users, run the script with the -UserType parameter as shown:

This report helps you identify and reclaim unused licenses for internal users, including those assigned through Microsoft Entra ID groups.

5. Identify Inactive Licenses Assigned to External Users

Licenses assigned to external users can remain active even when unused, cluttering your tenant and complicating management. To identify unused licenses for external users, use the –UserType parameter as follows:

This report helps to clean up unused licenses of inactive external accounts and protect your environment from potential risks.

6. Analyse Unused Licenses for Sign-In Enabled Users

Even after switching teams or completing a project, some users keep an active license because their sign-in is still enabled. Keeping these licenses assigned leads to wasted subscription costs and prevents resources from being reallocated to active users.

Such licenses can be identified by using the –UserState parameter as below:

This report helps reclaim unused licenses from inactive enabled accounts, ensuring efficient resource usage and reducing subscription waste.

7. Track Unused Licenses for Sign-In Disabled Users

Disabled accounts often retain active licenses, leading to wasted subscriptions and compliance risks. To detect these licenses, execute the script with the –UserState parameter as below:

This report helps find unused licenses from disabled accounts. This helps in reducing licensing costs and preventing misuse.

8. Spot Unused Free Microsoft 365 Subscriptions

Free licenses are often assigned to temporary, intern, or test accounts but remain unused. To identify these free unused licenses, you can run the script with the –LicenseType parameteras below:

This report helps you to quickly spot idle free licenses, reduce clutter, and ensure your Microsoft 365 license usage is efficient and cost-effective.

9. Find Inactive Paid Microsoft 365 Subscriptions

Paid licenses are costly and must be monitored closely. For instance, contractors or temporary staff may complete their work, but their licenses remain assigned long after they leave. To identify such unused paid licenses, you can filter the script using the -LicenseType parameter as shown below:

The report highlights unused paid licenses so you can safely reclaim and reassign them.

10. Reclaim Inactive Trial Microsoft 365 Subscriptions

Trial licenses are useful for testing and pilot projects, but they often remain assigned even after trials expire. These unused licenses clutter the tenant and distort license usage reports.

To identify these unused trial licenses, run the script with the –LicenseType parameter as shown:

This report helps you reclaim inactive trial licenses, keep your license inventory clean, and maintain accurate reporting.

We hope this blog helped you understand how to detect inactive Microsoft 365 licenses using users’ last successful sign-in. If you have any questions, feel free to drop them in the comments below!

Share article