PRACTITIONER GUIDE | IDENTITY SECURITY
Practitioner GuideUpdated 9 min read

Entra ID Service Principal Hidden Credentials: The Secrets Your Portal Does Not Show You

Portal blind spot
SP-level credentials are only visible via Graph API -- the portal UI routes you to App Registrations only
600+
First-party Microsoft apps auto-provisioned in every new Entra tenant -- each can hold SP-level credentials
passwordCredentials
Graph API property to query on servicePrincipal objects for secrets not visible in portal

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

The Entra ID portal creates a misleading mental model: credentials live under App Registrations. That is partly true. But any service principal -- including the hundreds of first-party Microsoft applications that exist in every tenant by default -- can independently hold credentials added directly to the SP object via the Graph API. There is no portal blade for this. The only way to see them is with API calls or PowerShell. Attackers who compromise a high-privilege account can add a credential to a first-party SP (bypassing the App Registration they do not own) and authenticate as that application indefinitely. This guide shows how to find all of them.

How SP-Level Credentials Differ from App Registration Credentials

The App Registration object (Microsoft.Graph.Application) is the canonical definition of a custom application in your tenant. When you add a client secret under App Registrations > Certificates and Secrets, you are adding it to the Application object. The service principal object (Microsoft.Graph.ServicePrincipal) is a separate object -- the local instantiation of the application in this tenant. For applications registered in other tenants (third-party SaaS, partner apps) or first-party Microsoft apps, there is no App Registration in your tenant -- only the service principal. Both the Application object (via POST /applications/{id}/addPassword) and the ServicePrincipal object (via POST /servicePrincipals/{id}/addPassword) accept credentials independently. The portal's App Registrations blade only shows Application object credentials. The Enterprise Applications blade shows the service principal but provides no credentials UI. Result: any credential added to a ServicePrincipal object is portal-invisible.

Enumerate All Service Principal Credentials via Graph API

Using the Microsoft Graph PowerShell SDK: Connect-MgGraph -Scopes 'Application.Read.All'. Get all service principals with non-empty credential sets: Get-MgServicePrincipal -All | Where-Object { ($.PasswordCredentials.Count -gt 0) -or ($.KeyCredentials.Count -gt 0) } | Select-Object DisplayName, AppId, @{N='Secrets';E={$.PasswordCredentials.Count}}, @{N='Certs';E={$.KeyCredentials.Count}}, @{N='SecretExpiry';E={($.PasswordCredentials | Sort-Object EndDateTime -Descending | Select-Object -First 1).EndDateTime}}. This returns every SP across your tenant -- including Microsoft first-party apps -- that holds credentials. For each result: DisplayName tells you which app, SecretExpiry tells you when the credential expires. A first-party Microsoft app (DisplayName like 'Microsoft Graph', 'Office 365 SharePoint Online', 'Device Registration Service') with a non-Microsoft-issued credential is a red flag. Separately query App Registrations: Get-MgApplication -All | Where-Object { ($.PasswordCredentials.Count -gt 0) -or ($_.KeyCredentials.Count -gt 0) } | Select-Object DisplayName, AppId. Compare the two lists -- SPs with credentials that have no corresponding App Registration in your tenant (they belong to another tenant or are first-party) are the ones invisible in the portal.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

Detect Attacker-Added Credentials on Service Principals

The Entra ID audit log records credential additions to both Application and ServicePrincipal objects but categorizes them differently. Event: Update service principal -- Additional Details: operation type 'Add service principal credentials'. Search the Entra ID audit log: In Entra admin center > Monitoring > Audit logs > Service = Application Management > Activity = 'Update service principal' > filter for 'credentials' in the Details. Alternatively in Sentinel: AuditLogs | where OperationName == 'Update service principal' | where TargetResources[0].modifiedProperties has 'KeyDescription' | project TimeGenerated, InitiatedBy, TargetResources[0].displayName, Result. Alert on: credential additions to any first-party Microsoft SP (the DisplayName will match a known Microsoft application), credential additions during off-hours, credential additions by non-automated identities (a human admin adding a secret to a Microsoft SP is highly unusual), and credentials with unusually long lifetimes (1-2 years -- attackers prefer long-lived secrets for persistence). In MDI and Defender XDR: the 'Application credential modification' detection type covers some of these patterns.

Audit Risky SP Credential Configurations

Beyond hidden credentials, audit for these dangerous SP credential patterns. Over-permissioned SPs with active secrets: a service principal that holds credentials and is assigned a sensitive role (Global Admin, Exchange Admin, Application Admin) can be used by anyone who knows those credentials to authenticate as the application and use its permissions -- without any MFA requirement, because service principals are excluded from user-targeted MFA Conditional Access policies. Find them: Get-MgServicePrincipal -All | ForEach-Object { $sp = $; Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id | Where-Object { $.AppId -eq '00000003-0000-0000-c000-000000000000' } | ForEach-Object { [PSCustomObject]@{ SP = $sp.DisplayName; Role = $.PrincipalDisplayName; Credentials = $sp.PasswordCredentials.Count } } } | Where-Object { $.Credentials -gt 0 }. Additionally, check for SPs with Directory Roles: Get-MgDirectoryRoleMember -All (across all roles) and cross-reference against the SP credential list. Any SP with both active credentials and a privileged directory role assignment is a persistence risk if the credentials are leaked or attacker-added.

Reduce SP Credential Surface

After auditing, enforce the minimal credential footprint. Remove unnecessary SP credentials: for each SP with credentials that you cannot attribute to a current business need, remove them. For App Registration credentials: navigate to App Registrations > the app > Certificates and Secrets > delete expired or unrecognized secrets. For SP-level credentials (via API): Remove-MgServicePrincipalPassword -ServicePrincipalId [spId] -KeyId [credentialId]. Prefer managed identities over SP credentials: for Azure workloads, use managed identities (which have no exportable credentials) instead of SP client secrets. For third-party SaaS integrations: prefer federated identity credentials (workload identity federation) over client secrets where the SaaS supports it -- federated credentials do not use a shared secret at all. Create a credential inventory policy: require all SP credentials to be documented in your identity inventory, with an owner, an expiry no longer than 90 days, and a rotation process. Use Azure Policy or custom scripts to alert on credential additions without an associated change ticket.

The bottom line

The Entra ID portal gives a false sense of completeness for credential auditing. Service principal-level credentials on both custom and first-party Microsoft apps are invisible in the portal and require Graph API queries to discover. Run the PowerShell enumeration quarterly, alert on audit log events for SP credential additions -- especially on first-party Microsoft apps -- and enforce managed identity or federated credentials over client secrets wherever possible.

Frequently asked questions

Can Conditional Access policies prevent authentication using SP-level credentials?

Standard Conditional Access user policies do not apply to service principal (non-interactive / application-only) authentication flows. MFA requirements, compliant device requirements, and sign-in risk conditions are all user-targeted and do not fire for application credentials. Conditional Access for workload identities (a separate CA policy type) can enforce location-based restrictions on service principal sign-ins. Configure these policies for high-privilege SPs -- restrict authentication to known Azure IP ranges or specific managed identity resource IDs where feasible.

How do I find the AppId of first-party Microsoft service principals to filter them out of my results?

First-party Microsoft service principals have a published AppId list. Common ones: Microsoft Graph (00000003-0000-0000-c000-000000000000), SharePoint Online (00000003-0000-0ff1-ce00-000000000000), Exchange Online (00000002-0000-0ff1-ce00-000000000000). The full list is available from the Microsoft Identity Platform documentation and via the Microsoft Graph API (list all servicePrincipals where AppOwnerOrganizationId equals f8cdef31-a31e-4b4a-93e4-5f571e91255a -- Microsoft's internal tenant ID). Any SP in your tenant with that owner organization ID is a first-party app -- these should not have customer-added credentials.

What permissions are needed to add credentials to a service principal?

The caller needs either Global Administrator, Application Administrator, or Cloud Application Administrator directory role -- or the owner of the specific service principal object. This means that Application Administrator is a sufficient privilege to add credentials to any SP, including first-party Microsoft apps. Application Administrator is frequently treated as a lower-risk role than Global Admin, but credential addition to high-privilege SPs makes it a Tier-0-equivalent role in practice.

Is there a way to prevent credentials from being added to service principals entirely?

There is no built-in Entra ID policy to globally block SP-level credential additions the way App Registration password policies can restrict credential types. You can restrict who holds the Application Administrator and Cloud Application Administrator roles (which are the minimum roles needed to add SP credentials), monitor via the audit log, and use Conditional Access for workload identities to restrict where SP credentials can authenticate from. Full prevention would require a custom access restriction framework or regular automated remediation scripts.

What is the difference between an App Registration credential and a Service Principal credential?

An App Registration (application object) is the definition of the application -- its permissions, redirect URIs, and credentials are defined here. The Service Principal is the instance of the application within a specific tenant. For multi-tenant apps, there is one App Registration (owned by the app publisher's tenant) and a Service Principal in every tenant where it is consented. Credentials can be added to both: App Registration credentials are managed by the app owner (publisher) and used when the app authenticates to its own tenant. Service Principal credentials added directly to the SP object in a customer tenant allow the SP to authenticate in that customer tenant independently of the App Registration. The SP-level credential is the dangerous one to monitor -- it is an additional authentication path that bypasses the app publisher's own credential management.

How do you remediate a service principal that has accumulated excessive Microsoft Graph API permissions over time?

Remediate service principal over-permissioning by auditing actual API call patterns against the declared permission scope. Use the Entra ID Service Principal sign-in logs (under Monitoring > Sign-in logs > Service principal sign-ins) filtered to the target SP to see which APIs it actually calls: the resource URI shows the service called, and the scope claim in the token shows the permissions used. Compare actual usage against the consented permissions (visible in Entra admin center > App registrations > [app] > API permissions). Remove any permission scope that has not appeared in actual API calls over the past 30-90 days. For application permissions (not delegated): removing an application permission requires revoking the admin consent for that permission and updating the app's token to exclude it -- the change takes effect at the next token acquisition. If the service principal is a third-party application, work with the vendor to request a new app registration with reduced permissions rather than modifying the existing one. For service principals under your control, update the app registration to remove the unneeded permission declarations and redeploy. Implement a quarterly review cycle: any SP with more than 5 application permissions should require documented justification for each.

Sources & references

  1. Microsoft Graph API: servicePrincipal addPassword
  2. Semperis: unOAuthorized: Privilege Elevation via Microsoft Applications

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.