Microsoft Entra ID governance

How to find unused applications in Microsoft Entra ID

List enterprise apps with no recent sign-in with Microsoft Graph PowerShell, review service principal sign-in activity in the Entra admin centre, or use Altivane's Applications report.

By the Published

To find unused applications in Microsoft Entra ID, read each enterprise application's last sign-in from the service principal sign-in activity report and keep those with none in the period you choose. The report needs Microsoft Entra ID P1 or P2 and is in preview, on the beta Microsoft Graph endpoint. Its last activity can include partial sign-ins, so a recent date alone doesn't prove the app was used.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of apps and managed identities with no sign-in in 180 days or ever.
Admin centreA look at 1 app's last activity, or a short list of apps.
AltivaneRecommended for recurring reviews, with each app's granted permissions on the same row.

Before you start

Use an account in the Reports Reader, Security Reader or Security Administrator role to read the sign-in activity. The tenant needs Microsoft Entra ID P1 or P2. The PowerShell example requests Application.Read.All and AuditLog.Read.All; your organisation may require administrator consent.

Know what the data says. The report gives each app's most recent sign-in, whether it signed in as a client or was called as a resource, with a user or on its own. An app with no sign-in recorded has no entry. The examples leave out the apps Microsoft owns. They read and export; they don't disable or delete any app.

Option 1

Find unused applications with PowerShell

Install the modules once, then connect, read the sign-in activity and export the apps with no sign-in in the period.

PowerShell
# Install once, if the modules are not already installed.
$modules = 'Microsoft.Graph.Authentication', 'Microsoft.Graph.Applications',
    'Microsoft.Graph.Beta.Reports'
Install-Module $modules -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'Application.Read.All', 'AuditLog.Read.All' -NoWelcome
try {
    $days = 180
    $cutoff = (Get-Date).ToUniversalTime().AddDays(-$days)
    # The 2 tenants that own Microsoft's apps.
    $microsoft = 'f8cdef31-a31e-4b4a-93e4-5f571e91255a', '72f988bf-86f1-41af-91ab-2d7cd011db47'
    $lastSignIn = @{}
    Get-MgBetaReportServicePrincipalSignInActivity -All | ForEach-Object {
        $lastSignIn[$_.AppId] = $_.LastSignInActivity.LastSignInDateTime
    }
    $properties = 'id', 'appId', 'displayName', 'servicePrincipalType',
        'appOwnerOrganizationId', 'accountEnabled'
    $apps = @(Get-MgServicePrincipal -All -Property $properties | Where-Object {
        $_.ServicePrincipalType -in 'Application', 'ManagedIdentity' -and
            $_.AppOwnerOrganizationId -notin $microsoft
    })
    $report = @(foreach ($app in $apps | Sort-Object DisplayName) {
        $last = $lastSignIn[$app.AppId]
        if ($last -and $last.ToUniversalTime() -ge $cutoff) { continue }
        [pscustomobject]@{
            Application = $app.DisplayName
            Type        = $app.ServicePrincipalType
            Enabled     = $app.AccountEnabled
            LastSignIn  = $last
            AppId       = $app.AppId
        }
    })
    if ($report.Count -eq 0) {
        Write-Output "Every application signed in within the last $days days."
    } else {
        $report | Export-Csv -Path './unused-applications.csv' -NoTypeInformation -Encoding utf8
        Write-Output "$($report.Count) of $($apps.Count) applications are unused."
    }
} finally {
    Disconnect-MgGraph | Out-Null
}

The script reads the sign-in activity once, then keeps every application and managed identity not owned by Microsoft whose last sign-in is older than 180 days or missing. LastSignIn is blank for an app with no sign-in recorded. Change $days for another period. An unused app can still hold permissions, so check what it was granted before you remove it.

Check 1 application

Reconnect with Connect-MgGraph, then read 1 app's activity by its application ID.

PowerShell
# Run while connected to Microsoft Graph. Replace the example application ID.
$filter = "appId eq '00000000-0000-0000-0000-000000000000'"
Get-MgBetaReportServicePrincipalSignInActivity -Filter $filter |
    Select-Object AppId, LastSignInActivity, DelegatedClientSignInActivity,
        ApplicationAuthenticationClientSignInActivity

Each activity has its own LastSignInDateTime, so you can tell an app that signs in with users from one that signs in on its own.

Option 2

Review app activity in the admin centre

  1. Sign in to the Microsoft Entra admin centre for the correct tenant as at least a Reports Reader.
  2. Go to Entra ID > Monitoring & health > Usage & insights.
  3. Select Service principal sign-in activity (preview) to see the last activity date for each service principal.
  4. Select View more details on a row for the app's client and object IDs and how it signed in.
  5. To see 1 app's sign-ins by day, select Microsoft Entra application activity (preview), then View sign-in activity for the app.

This suits a look at 1 app or a short list. The page doesn't mark an app as unused or show what it was granted, so for a list to act on, use PowerShell or a report.

Common questions

Is an app with no recent sign-in safe to delete?

Not always. An app used once a year, or one that waits to be called, can look unused. Check its owner and its permissions first; see how to review app permissions. A deleted app registration can be restored for 30 days.

Why doesn't a recent date prove the app works?

Microsoft says last activity can include partial sign-ins and other incomplete activity that isn't in the sign-in logs. A date alone doesn't show that the sign-in completed or that a token was issued.

Why does the report return an error or nothing at all?

Check the licence and the role first: the report needs Microsoft Entra ID P1 or P2 and 1 of the reader roles above. It's a beta API, available in Microsoft's global service and not in the US Government or China clouds.

Microsoft references

Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us