Join our Newsletter — 33% off our NHI Course
Home› Guides› How to find and remove stale service principals…
Guide Non-Human Identity (NHI)

How to find and remove stale service principals in Entra ID: A safe disable, wait and delete runbook

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 28 October 2026 10 min read
On this page

Most Entra ID tenants hold hundreds of service principals that nobody has signed in with for months, and each one can still carry credentials, admin consent and app role assignments. A stale service principal is free persistence for an attacker: add a secret, request a token, and the activity looks like a normal application. This runbook shows how to find stale service principals with the sign-in activity reports and the Entra recommendations, how to disable them first, delete them safely and restore them inside the 30 day window if something breaks. It is written for Entra administrators and identity engineers who need a repeatable clean-up, not a one-off purge. For the background on applications, service principals and consent, see the Entra ID Applications and Consent Guide.

Key takeaways

  • Use the activity reports, not guesswork. The Graph beta reports servicePrincipalSignInActivities and appCredentialSignInActivities give the last sign-in per service principal and per credential.
  • Disable before you delete. Setting accountEnabled to false stops all token issuance in the tenant while keeping the configuration, so a missed dependency is a one-line fix.
  • Deletion is reversible for 30 days. Deleted service principals sit in the recycle bin and can be restored, but Conditional Access policies tied to them are not brought back.
  • Filter out what you cannot or should not touch. Microsoft first-party apps and managed identities behave differently and need their own handling.
  • Remove credentials even when you keep the app. Unused secrets and certificates on live apps are the easier attacker target, and Entra flags credentials unused for 30 days.

When you need this

Run this procedure when any of the following apply:

  • Tenant hygiene: the Entra admin center shows the Remove unused applications recommendation (API name staleApps), which flags apps not used for over 90 days, or Remove unused credentials from applications (staleAppCreds), which flags credentials unused for 30 days.
  • Incident follow-up: after an investigation found an attacker adding credentials to an existing application (ATT&CK T1098.001 Additional Cloud Credentials). Storm-1283 did exactly this to line-of-business apps and then used them to run cryptomining VMs, as covered in the Storm-1283 OAuth apps abuse analysis.
  • Legacy and test tenants: the Microsoft Midnight Blizzard breach started from a forgotten test tenant and a legacy test OAuth application that still had elevated access to the corporate environment.
  • Audit findings: an access review or audit asks for evidence that dormant non-human accounts are disabled (NIST SP 800-53 AC-2(3) Disable Accounts).

Before you start

RequirementDetail
Read-only discoveryGraph permission AuditLog.Read.All (least privileged) for the two activity reports, plus a role such as Reports Reader, Security Reader or Security Administrator for delegated use
RecommendationsReports Reader, Security Reader or Global Reader to view; Security Administrator to update status
Disable, delete, restoreCloud Application Administrator, Application Administrator or owner of the service principal; scope Application.ReadWrite.All
ToolingMicrosoft Graph PowerShell (Install-Module Microsoft.Graph) or Microsoft Entra PowerShell; Graph Explorer for one-off calls
API statusThe activity reports are on the /beta endpoint and Microsoft does not support beta for production use. Treat results as evidence to review, not as an automated delete trigger
Change recordA ticket listing each service principal object ID, appId, owners and permissions before any change

Agree a dormancy threshold before you query. Entra's own recommendation uses 90 days for apps; many organisations add a quarter-end or annual job buffer for batch integrations and pick 180 days for automatic disable. The NHI Dormancy Detection guide covers how to choose thresholds across platforms.

Step-by-step

Steps 1 to 4 are read-only. Step 5 changes the tenant but is reversible. Step 6 is destructive after the 30 day recycle bin period.

  1. Export every service principal with its type and owner tenant. The servicePrincipalType property separates Application, ManagedIdentity, Legacy and ServiceIdentity (agent identities). appOwnerOrganizationId holds the tenant where the application is registered, which lets you split your own apps from third-party and Microsoft apps.
    Connect-MgGraph -Scopes "Application.Read.All","AuditLog.Read.All"
    Get-MgServicePrincipal -All -Property Id,AppId,DisplayName,ServicePrincipalType,AppOwnerOrganizationId,AccountEnabled,KeyCredentials,PasswordCredentials |
      Select-Object Id,AppId,DisplayName,ServicePrincipalType,AppOwnerOrganizationId,AccountEnabled |
      Export-Csv sp_inventory.csv -NoTypeInformation
  2. Pull last sign-in activity per service principal. The report returns lastSignInActivity and four breakdowns: delegatedClientSignInActivity, delegatedResourceSignInActivity, applicationAuthenticationClientSignInActivity and applicationAuthenticationResourceSignInActivity, each with lastSignInDateTime.
    GET https://graph.microsoft.com/beta/reports/servicePrincipalSignInActivities
    GET https://graph.microsoft.com/beta/reports/servicePrincipalSignInActivities?$filter=appId eq '{appId}'
    Join on appId. A service principal with no row, or with a lastSignInDateTime older than your threshold, is a candidate. Check the resource-side fields too: an API that other apps call shows activity there, not on the client side.
  3. Pull credential-level activity. appCredentialSignInActivities returns one row per credential with keyId, keyType (certificate or secret), credentialOrigin (application or servicePrincipal), the expiry and signInActivity.lastSignInDateTime.
    GET https://graph.microsoft.com/beta/reports/appCredentialSignInActivities?$filter=appId eq '{appId}'
    This finds the common case of a live app carrying an old secret nobody uses.
  4. Cross-check the recommendations and enrich. In the Microsoft Entra admin center go to Entra ID > Overview > Recommendations and open Remove unused applications; the Impacted resources list should agree with your query. For each candidate record owners (GET /servicePrincipals/{id}/owners), app role assignments, delegated grants (oauth2PermissionGrants) and Azure RBAC assignments. Contact owners with a deadline. No owner and high privilege moves a candidate to the front of the queue.
  5. Disable the candidates (reversible). Disabling prevents all tokens being issued for the application in this tenant. Portal: Entra ID > Enterprise apps > All applications > select the app > Properties > Enabled for users to sign-in? = No > Save. Graph PowerShell:
    $sp = Get-MgServicePrincipal -Filter "appId eq '{appId}'"
    Update-MgServicePrincipal -ServicePrincipalId $sp.Id -AccountEnabled:$false
    Or Graph: PATCH /v1.0/servicePrincipals/{id} with {"accountEnabled": false}. Record the change in the service principal's notes field (up to 1,024 characters) or a tag so the next reviewer sees why. Leave it disabled for a full business cycle, usually 30 to 90 days.
  6. Delete (destructive after 30 days). When the disable period passes with no complaints, delete. Portal: Enterprise apps > All applications > app > Properties > Delete. Graph PowerShell: Remove-MgServicePrincipal -ServicePrincipalId '{id}', or DELETE /v1.0/servicePrincipals/{id}. For apps registered in your own tenant, decide whether to delete the app registration too: deleting the registration also deletes its service principal. Remove unused credentials from apps you keep through App registrations > app > Certificates & secrets.

Verify it worked

  • Disabled state: Get-MgServicePrincipal -ServicePrincipalId '{id}' -Property AccountEnabled returns False.
  • No new tokens: the service principal sign-in log (the log that records apps authenticating with their own certificate or secret) shows failures, not successes, for the appId. Managed identities sign in to a separate managed identity log, so check that one for those.
  • Deletion landed in the recycle bin: GET /v1.0/directory/deletedItems/microsoft.graph.servicePrincipal?$filter=appId eq '{appId}' returns the object.
  • Recommendation status: the Impacted resources count for Remove unused applications falls on the next refresh. Mark anything you deliberately keep as Dismissed with a reason.
  • Audit trail: the Entra audit log shows the update and delete operations against your change ticket.

Rollback and common errors

SituationFix
A business process broke after disableSet accountEnabled back to true; record the owner and the real usage pattern so the next review does not repeat it
Deleted the wrong service principal (within 30 days)Restore-MgDirectoryDeletedItem -DirectoryObjectId {id} or POST /v1.0/directory/deletedItems/{id}/restore. Re-create any Conditional Access targeting manually, because restore does not bring back previous policies
Deleted more than 30 days agoNot recoverable. Re-register or re-consent the app and re-grant permissions from your pre-change export
Name filter matched two objectsDisplay names are not unique. Always filter on appId or object Id
Managed identity appears staleManaged identity service principals cannot be deleted or restored by customers in Entra; remove the managed identity from the Azure resource instead
Microsoft app flagged by your scriptExclude Microsoft-owned apps; Entra's own recommendation already does. Disable a first-party app only after reading Microsoft guidance for that app
Beta call returns 403The caller lacks AuditLog.Read.All or the delegated user lacks a reports role
Multitenant app you publishDisabling the service principal affects your tenant only. To stop it everywhere, deactivate the application registration instead

Do not permanently purge from the recycle bin (Remove-MgDirectoryDeletedItem) as part of routine clean-up. Let the 30 day window run unless a security incident requires immediate removal.

Hardening afterwards

  • Schedule it: run steps 1 to 3 monthly as an automation using an application with AuditLog.Read.All and Application.Read.All only. Keep write permissions in a separate, human-approved step.
  • Require two owners: Microsoft's Graph reference recommends at least two owners per service principal. Make ownership a creation gate and re-attest it in access reviews.
  • Prefer certificates or federation over secrets: for workloads outside Azure, replace client secrets with workload identity federation. See the Workload Identity Federation Guide and the Azure Entra Client Secrets Security Guide.
  • Alert on credential additions: new secrets or certificates on dormant apps are a classic persistence signal. The Entra ID Sign-In and Audit Log Detection Guide covers the audit events to watch.
  • Close the loop with inventory: feed results into your NHI inventory so a deleted principal is retired everywhere. See NHI Offboarding and Decommissioning Guide.

Metrics that show it is working

MetricTarget to aim for
Service principals with no sign-in beyond threshold and still enabledZero after each cycle
Applications with credentials unused for 30 daysFalling month on month
Service principals with fewer than two ownersZero for privileged apps
Restores within 30 days of deletionLow; a high rate means the disable period is too short
Median days from flag to disableUnder 30

Framework mapping

FrameworkReferenceHow this runbook supports it
NIST SP 800-53 Rev 5AC-2, AC-2(3), IA-4Account management, disabling inactive accounts, identifier retirement
NIST CSF 2.0PR.AA-01, PR.AA-05Identities and credentials for services are managed; permissions reviewed
MITRE ATT&CKT1098.001, T1078.004Removes dormant apps that attackers add credentials to or use as cloud accounts
CIS Controls v8.15.3 Disable Dormant AccountsSame intent applied to workload identities

Small tenant or large estate

A tenant with a few dozen custom apps can run this by hand each quarter from the portal recommendation. An estate with thousands of service principals should script steps 1 to 3, group candidates by owning team and privilege, and disable in waves (low privilege first, then apps with Microsoft Graph application permissions or Azure subscription roles once owners have confirmed). In both cases, apps holding high-impact application permissions deserve a named reviewer, because a stale app with directory or mailbox write permissions is the highest-value target.

Practitioner checklist

  • Export all service principals with type, owner tenant, owners and credentials before any change.
  • Join the two Graph activity reports on appId and apply an agreed dormancy threshold.
  • Exclude Microsoft-owned apps and handle managed identities on the Azure resource.
  • Notify owners with a deadline; treat ownerless privileged apps as top priority.
  • Disable with accountEnabled false and record the reason in notes or tags.
  • Delete only after a full business cycle with no breakage.
  • Remove unused secrets and certificates from apps you keep.
  • Keep the pre-change export so a restore or re-consent is quick.

Standards and references

Related NHI Mgmt Group resources: Entra ID Applications and Consent Guide · Azure RBAC and Service Principals Guide · NHI Dormancy Detection · NHI Offboarding and Decommissioning Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 28 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.