All insights
Security OperationsZero Trust

Workload Identity Governance: The Over-Permissioned Attack Surface Boards Have Not Assessed

Service principals frequently hold more powerful permissions than any human identity in the tenant, bypass MFA entirely, and are rarely subject to access review. This ungoverned attack surface is a material risk that most boards have never been briefed on. This guide covers discovery, audit, and the governance controls required to bring workload identities under the same oversight regime as human access.

INSIGHTS OF 2026
12 min read
Practitioner Insight

Service Principal Security: The Hidden Risk in M365 Automation

Service principals are the identity backbone of automation in Microsoft 365 and Azure. Every Power Automate flow that calls the Graph API, every third-party SaaS integration, every backup solution, every monitoring tool, and every custom application that interacts with your tenant does so through a service principal. They are also, in the vast majority of organisations, the least monitored, least governed, and most over-permissioned identity type in the entire environment.

What Service Principals Are

In Entra ID, a service principal is the local representation of an application. When you consent to a third-party application (e.g., a backup tool that needs to read your mailboxes), Entra ID creates a service principal object in your tenant. This object holds the permissions, credentials, and configuration that allow the application to authenticate and access your resources.

There are three types:

Application (first-party): Microsoft's own applications - Exchange Online, SharePoint Online, Microsoft Teams. These are pre-consented and managed by Microsoft.

Application (third-party): External vendor applications that you have granted consent to. These are the primary risk surface.

Managed Identity: Azure resource identities (system-assigned or user-assigned) used for Azure-to-Azure authentication. These are lower risk because they do not use exportable credentials.

The risk concentrates in third-party application service principals. When you click "Grant admin consent" for a SaaS application requesting Microsoft Graph permissions, you are creating a non-interactive identity that can access your tenant data 24/7, without MFA, without Conditional Access (by default), and often with permissions far exceeding what the application actually needs.

Why Service Principals Are Risky

No MFA: Service principals authenticate with certificates or client secrets (passwords), not interactive credentials. MFA does not apply. If the credential is compromised, the attacker has direct, unimpeded access.

No Conditional Access (by default): Until Workload Identity Conditional Access was introduced, service principals were exempt from all Conditional Access policies. Even now, Workload Identity CA requires P2 licensing and explicit configuration - most organisations have not implemented it.

Over-permissioned: The Graph API permission model is coarse. Applications frequently request Directory.ReadWrite.All, Mail.ReadWrite, or Sites.Read.All - permissions that grant access to every user's directory data, every mailbox, or every SharePoint site in the tenant. Vendors request broad permissions because it is easier than requesting granular permissions, and administrators grant them because the consent dialog does not clearly communicate the blast radius.

Long-lived credentials: Client secrets have a maximum lifetime of 2 years (previously unlimited). Many organisations have service principals with secrets that were created years ago and never rotated. If those secrets are stored in source code, configuration files, or shared documents, they represent a persistent backdoor.

Non-interactive: Service principal activity does not generate the same visibility as user sign-ins. Standard sign-in log queries exclude service principal sign-ins unless you explicitly filter for them. Attackers who compromise a service principal can operate silently.

Discovery and Audit

Step 1: Inventory all service principals

Navigate to Entra ID > Enterprise applications > All applications. Filter by "Application type: Enterprise applications" to see third-party service principals. The list will be longer than expected, a typical M365 tenant has 50-200+ third-party service principals.

Using Microsoft Graph PowerShell:

Connect-MgGraph -Scopes "Application.Read.All"
$servicePrincipals = Get-MgServicePrincipal -All -Filter "servicePrincipalType eq 'Application'"
$servicePrincipals | Select-Object DisplayName, AppId, CreatedDateTime,
    @{N='SignInAudience';E={$_.SignInAudience}},
    @{N='CredentialCount';E={($_.KeyCredentials.Count + $_.PasswordCredentials.Count)}}
| Export-CSV -Path "service-principals.csv"

Step 2: Audit permissions

For each service principal, review the granted permissions. The critical permissions to flag:

  • Directory.ReadWrite.All - full read/write access to the entire directory
  • Mail.ReadWrite or Mail.Read - access to all mailboxes
  • Sites.ReadWrite.All - access to all SharePoint sites
  • Files.ReadWrite.All - access to all OneDrive files
  • User.ReadWrite.All - ability to modify all user accounts
  • RoleManagement.ReadWrite.Directory - ability to assign admin roles
$sp = Get-MgServicePrincipal -ServicePrincipalId "<object-id>"
$appRoles = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id
$appRoles | ForEach-Object {
    $resource = Get-MgServicePrincipal -ServicePrincipalId $_.ResourceId
    [PSCustomObject]@{
        App = $sp.DisplayName
        Permission = ($resource.AppRoles | Where-Object { $_.Id -eq $_.AppRoleId }).Value
        Resource = $resource.DisplayName
    }
}

Step 3: Identify stale and unused service principals

Check sign-in activity for each service principal under Entra ID > Enterprise applications > [app] > Sign-in logs (select the "Service principal sign-ins" tab). Service principals that have not authenticated in 90+ days should be reviewed for decommissioning.

Permission Scoping

The remediation strategy is to reduce permissions to the minimum required:

Replace broad permissions with granular ones: Instead of Mail.ReadWrite (all mailboxes), use Mail.ReadWrite with an application access policy that restricts the service principal to specific mailboxes:

New-ApplicationAccessPolicy -AppId "<app-id>" -PolicyScopeGroupId "<security-group-id>" -AccessRight RestrictAccess -Description "Restrict mail access to IT mailboxes only"

Use delegated permissions where possible: Application permissions (app-only) grant tenant-wide access. Delegated permissions are scoped to the signed-in user's access. Where a service principal operates on behalf of a specific user, prefer delegated permissions.

Implement resource-specific consent (RSC): For Teams applications, RSC allows permissions scoped to specific teams rather than all teams in the tenant.

Credential Rotation

Client secrets: Implement a 90-day rotation schedule for all client secrets. Use Azure Key Vault to store secrets and automate rotation. Never store secrets in application configuration files, environment variables on shared servers, or documentation.

Certificates: Prefer certificates over client secrets. Certificates are cryptographically stronger and can be managed through Azure Key Vault with automatic renewal. Configure the service principal to authenticate with a certificate:

$cert = New-SelfSignedCertificate -Subject "CN=MyApp" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy NonExportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256 -NotAfter (Get-Date).AddMonths(12)

Upload the public certificate to the app registration in Entra ID and remove any existing client secrets.

Managed Identity: Where possible, replace service principals with managed identities. A managed identity's credentials are managed by Azure and cannot be extracted. For Azure-hosted applications (App Service, Functions, Logic Apps), managed identity eliminates the credential management burden entirely.

Monitoring with Sentinel

Deploy Sentinel analytics rules specifically for service principal activity:

Detect new high-privilege consent:

AuditLogs
| where OperationName == "Consent to application"
| extend Permissions = tostring(TargetResources[0].modifiedProperties)
| where Permissions contains "Directory.ReadWrite" or Permissions contains "Mail.ReadWrite" or Permissions contains "Sites.ReadWrite"
| project TimeGenerated, InitiatedBy, TargetResources, Permissions

Detect service principal sign-in from unusual IP:

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(24h)
| summarize KnownIPs = make_set(IPAddress) by ServicePrincipalId, AppId
| join kind=inner (
    AADServicePrincipalSignInLogs
    | where TimeGenerated > ago(1h)
) on ServicePrincipalId
| where IPAddress !in (KnownIPs)
| project TimeGenerated, ServicePrincipalName, AppId, IPAddress, Location

Detect credential addition to existing app:

AuditLogs
| where OperationName in ("Add service principal credentials", "Update application – Certificates and secrets management")
| project TimeGenerated, InitiatedBy, TargetResources, OperationName

This last rule is critical - attackers who compromise an admin account often add credentials to existing high-privilege service principals rather than creating new ones, because existing service principals are less likely to be noticed.

Workload Identity Conditional Access

For organisations with Entra ID P2 (or the Workload Identities Premium licence), Workload Identity Conditional Access applies policy controls to service principals:

Navigate to Entra ID > Security > Conditional Access > Create policy. Under "Users or workload identities," select "Workload identities" and target specific service principals. Configure:

  • Location condition: Block service principal authentication from outside expected IP ranges. If a backup tool always authenticates from a specific Azure region, block authentication from all other locations.
  • Risk condition: Block when Entra ID detects anomalous workload identity behaviour (unusual authentication patterns, impossible travel for the service principal).

Service principal security is not glamorous, but it is one of the highest-impact improvements an organisation can make. A compromised user account is dangerous; a compromised service principal with Directory.ReadWrite.All can be far more damaging. The organisations that audit, scope, rotate, and monitor their workload identities are the organisations that survive supply-chain attacks and third-party breaches.