Every December I set aside time to go through app registrations and enterprise applications in Microsoft Entra ID and look for entries nobody uses anymore. Almost every tenant I work in has its own graveyard of test apps, migration helpers and one-off integrations. Most of them were forgotten long ago, and many still hold far more permissions than they ever needed. That is more than untidy. It is a genuine security and compliance risk. Microsoft now shows its “Remove unused applications” and “Renew expiring service principal credentials” recommendations more prominently in the Entra admin center, but the practical work is still left to admins. You have to figure out which apps are really unused, and then remove them without breaking anything.

Unused apps in Entra ID carry real risk, and Microsoft's recommendations are only the starting point

Attackers go after OAuth apps and old service principals more and more often, particularly the ones holding high-privilege application permissions such as Directory.ReadWrite.All or Mail.ReadWrite. These apps tend to outlive the project they were built for, and their broad access stays in place the whole time. Microsoft's recommendations for unused apps (documented here) and for expiring credentials give you a sensible place to begin. I wouldn't follow them blindly, though. The hard part is working out actual usage and risk. An app with no activity, no owner and wide permissions should make you suspicious, but check it properly before you delete anything.

Service principal sign-ins and owner checks show which apps are actually in use

My main source of truth is the service principal sign-in activity. Under Microsoft Entra admin center → Enterprise applications → Usage & insights → Sign-ins you can see when each app last authenticated, for user tokens as well as app tokens. In bigger environments the Microsoft Graph API helps a lot, because it now exposes the servicePrincipalSignInActivity property (you need the Directory Reader or Application Administrator role). That makes automated discovery of dormant apps much easier. When an app has no recent sign-in, no assigned roles and no owner, it is usually a good candidate for cleanup.

Practical tip: In the Entra portal, sort the Enterprise Applications list by “Last sign-in” and you'll immediately see which apps nobody has touched in months.

I also always check for apps with no owners. In the Entra admin center you can filter under Enterprise applications → All applications → Owners to find them quickly. Privileged apps that nobody is responsible for are the ones that worry me most. I'd strongly recommend a defined process for assigning and reviewing app owners, ideally making an owner mandatory at registration. I wrote about this in an earlier post: /blog/app-governance-defender-cloud-apps-oauth.

Disabling an app before deleting it keeps the cleanup safe

Deleting an app straight away is risky. If something still depends on it, you find out the hard way. That's why I always work in phases. First I set Enabled for users to sign-in = No on the app's Properties tab. Authentication is blocked, but the object stays in place, so anything that breaks shows up quickly. I usually wait at least 14 days, sometimes a full month, before I delete. The actual removal happens in the Entra admin center through Enterprise applications → Delete, and app registrations are deleted under App registrations. Every deletion is a soft delete for 30 days, so you can still recover the app if you need to. Microsoft's full guide is here: Remove enterprise applications.

This simple diagram shows the process I follow:

flowchart TD
  FindUnused["Identify unused apps"] --> DisableSignIn["Disable sign-in"]
  DisableSignIn --> WaitPeriod["Wait period (14–30 days)"]
  WaitPeriod --> DeleteApp["Delete app"]
  DeleteApp --> SoftDelete["Soft Delete (30 days)"]
  SoftDelete --> Gone["Permanently removed"]

Figure: Recommended cleanup process for unused apps in Entra ID.

If an app uses client secrets, the cleanup is a good moment to look for old credentials that never expire. It's also worth asking whether privileged service principals could move to workload identity federation or managed identities instead. I go into that in /blog/replace-client-secrets-workload-identity-federation.

Graph PowerShell automates the search, but a few pitfalls remain

In larger tenants, automating this with Graph PowerShell saves a lot of time. To list all app registrations without owners (PowerShell 7, Microsoft.Graph.Applications module, Application Administrator role):

Get-MgApplication | Where-Object { -not $_.Owners }

For unused apps, query the servicePrincipalSignInActivity property through the Graph API. Keep in mind that this only covers enterprise applications (service principals). Pure app registrations without an associated service principal won't show up. And always check twice, because some apps are core parts of Microsoft 365 (Teams, Exchange Online and so on). Never delete those.

App hygiene works best as a recurring routine rather than a one-off

Unused apps in Entra ID will keep coming back as a security risk, but they also give you a reason to build better habits. Assigning owners, reviewing apps regularly and disabling before deleting is what separates a safe cleanup from an accidental outage. After the OAuth-based attacks of the past year (I covered them in /blog/midnight-blizzard-lessons-oauth-apps-test-tenants), I don't see proactive cleanup as optional anymore. Use Microsoft's recommendations, combine them with a careful process driven by app owners, and make the cleanup a regular task. Your tenants will be tidier and safer, and you'll start the new year with one less thing on your mind.