AppGov Score Blog

Check out our latest updates!

The Hidden Risks of Entra ID Application Ownership (Part 1)

November 20, 2025 Glenn Van Rymenant

The Hidden Risks of Defining Ownership on your Entra ID Applications

Assigning ownership to your application and service principal objects in Entra ID might seem like good governance, but it introduces significant security and privilege risks.

When assigned ownership, users can manage the credentials and modify high-impact settings on these objects – all without being assigned any administrator roles. These are privileged actions that pose significant risk, whether through intentional misuse or account compromise.

This article highlights the risks and explains why you should avoid assigning ownership to your application and service principal objects in Entra ID.

Risks of ownership on application objects

As a brief recap:

In Entra ID, an application usually consists of two related objects: the application object and the service principal object – ignoring multi-tenant and managed identity scenarios for simplicity.

The application object acts as a blueprint that specifies the application’s configuration, capabilities, and behavior. The service principal object is the representation of that blueprint within a specific tenant – the identity of the application used for most interactions.

When you assign someone as an owner of an Entra ID application object, you give them control over key parts of the app’s configuration, including credentials, permissions, and authentication behavior.

Owners can:

  • Manage client credentials (secrets or certificates)
  • Manage redirect URIs
  • Modify token or claims settings

Adding a client credential allows the owner to authenticate as the application itself using the client credentials grant flow. This means they can obtain access tokens including all the application permissions the application’s service principal is granted consent for in the tenant.

In other words, those permissions operate entirely under the application’s identity, without any interactive user sign-in. That design makes sense for legitimate service-to-service communication, but in the wrong hands, it can also enable privilege escalation or unauthorized access far beyond a user’s normal role.

For example, in the screenshot below, Megan – the marketing manager – is assigned ownership of a highly privileged Entra ID application object that has the Directory.ReadWrite.All application permission consented.

Application object ownership in the Entra admin portal

Figure1 : Application object ownership in the Entra admin portal.

 

A privileged application object with the Directory.ReadWrite.All Microsoft Graph API application permission consented.Figure 2: A privileged application object with the Directory.ReadWrite.All Microsoft Graph API application permission consented.

 

Addition of a client secret to the application object in the Entra admin center.

Figure3 : Addition of a client secret to the application object in the Entra admin center.

 

With that ownership in place, Megan – or anyone who compromises her account – could add a new client credential, request an access token, and gain directory-wide access by leveraging that Directory.ReadWrite.All permission. Even though Megan isn’t a Global Administrator, she (and any attacker) effectively has the same level of control through the app’s permissions.

With Megan being a typical business user exposed to common attack vectors, her account is far easier to compromise than a dedicated administrator account – a risk that should not be underestimated.

So, should you simply avoid assigning ownership on application objects with high privilege application permissions consented? Unfortunately, it doesn’t stop there.

Even without high-privilege application permissions consented, assigning ownership on application objects still exposes multiple lateral movement paths as owners can also:

  • Manage redirect URIs of the application, redirecting authentication responses – including authorization codes and tokens – to a malicious endpoint.
  • Allow less secure authentication flows such as the Device Code flow or Resource Owner Password Credential (ROPC) grant.
  • Modify token or claims settings in ways that expose information useful for reconnaissance or privilege escalation, such as group claims.

Each of these actions creates real opportunities for lateral movement, impersonation, and privilege escalation.

Risks of ownership on service principal objects

Ownership of service principal objects also introduces significant risk. Service principal object owners can:

  • Disable the application for sign-in.
    • Effectively blocking any user from authenticating to the application.
  • Remove the assignment requirement.
    • Allowing any user in the tenant to access the application (potentially).
  • Modify the single sign-on configuration.
    • Compromise authentication.
  • Modify the provisioning (SCIM) configuration.
    • Exposing sensitive data or misconfiguring how users and groups are provisioned.
  • View the activity logs (sign-in, audit, ...).
    • Providing valuable reconnaissance data.

A lesser-known risk is that service principal owners can also add client credentials directly to the service principal object – effectively the same as adding client credentials to the application object, with the crucial difference that these credentials aren’t visible in the Entra admin portal, making detection less likely.

To mitigate this risk, Microsoft introduced the App Instance Property Lock feature, which prevents modification of sensitive properties (see the screenshot below) on service principal objects and is enabled by default for all applications created after March 2024.

Unfortunately, this feature is managed on the application object and as you could have probably guessed, an application object owner can disable the feature for the application or unlock any of the properties.

This means assigning ownership to service principal objects can be just as risky as granting ownership to application objects. In both cases, a compromised owner account can be leveraged for privilege escalation or lateral movement.

App instance property lock configuration with property dropdown.

Figure 4: App instance property lock configuration with property dropdown.

Does restricting access to the Entra admin center reduce the risk?

Unfortunately, not really. While blocking (read) access to the Entra admin center using the setting below prevents owners from performing these actions in the admin center, it does not prevent them from performing these actions through other interfaces such as PowerShell modules. Conversely, it also defeats the purpose of assigning ownership in the first place, since owners can no longer manage the objects through the admin center.

Previously, users could still manage application and service principal objects they owned in the Entra admin center (or Azure portal) if they had a direct link to the object. Microsoft has since tightened this behavior, fully blocking access, even when the direct URL is known.

Adinistration center

Figure 5: User setting in Entra ID to restrict access to the Entra admin center for non-admin users (i.e.: users not assigned any administrator roles).

 

Even with the above Entra admin center restriction in place, owners can still interact with owned objects through other interfaces – which is one of the hidden risks of assigning ownership. Depending on the interface, access can sometimes be restricted by configuring the associated service principal (for example, by requiring assignment).

For instance:

Interface

Service principal displayname

AppId

Microsoft Graph Explorer (aka.ms/ge)

Graph Explorer

de8bc8b5-d9f9-48b1-a8ad-b748da725064

Microsoft Graph PowerShell SDK

Microsoft Graph Command Line Tools

14d82eec-204b-4c2f-b7e8-296a70dab67e

legacy AzureAD (Preview) PowerShell module

Azure Active Directory PowerShell

You will need to create the service principal object first as it will not be visible otherwise!

1b730954-1685-4b74-9bfd-dac224a7b894

Microsoft Graph

Microsoft Graph

00000003-0000-0000-c000-000000000000

 

Ideally, from a security perspective, you’d want to:

  • Avoid assigning ownership to application and service principal objects.
  • Restrict access to the Entra admin center for non-admin users.
  • Restrict access to the other interfaces for non-admin users (and admins alike).
  • Ensure App Instance Property Lock is enabled for all application objects under your control

Identifying application and service principal ownership with PowerShell

As you cannot directly filter on owned application and service principal objects in the Entra ID admin center, I provided some PowerShell code below that identifies owned application and service principal objects and exports it to a CSV. Alternatively, tools like ENow App Governance Accelerator can quickly identify objects with/without ownership.

 

 

# Connect to Microsoft Graph PowerShell

Connect-MgGraph -Scopes Application.Read.All -ContextScope Process

# Function to get all objects from a paged Microsoft Graph endpoint

# This is needed because Get-Mg* cmdlets do not return owners with all properties (only id)

function Get-MgGraphPaged {

    param(

        [Parameter(Mandatory = $true)][string]$Endpoint

    )

    $URI = "https://graph.microsoft.com/v1.0/$Endpoint"

    $Accumulator = @()

    do {

            $Response = Invoke-MgGraphRequest -Method GET -Uri $URI -ContentType

'application/json'

        if ($null -ne $Response.value) {

            $Accumulator += $Response.value

        }

        else {

            $Accumulator += $Response

        }

        $Next = $Response.'@odata.nextLink'

        if (-not $Next) { $Next = $Response.'@odata.nextlink' }

        $URI = $Next

    } while ($URI)

    return $Accumulator

}

# Get all service principal objects with their owners expanded

try {

    $ServicePrincipalObjects = Get-MgGraphPaged -Endpoint

"servicePrincipals?`$expand=owners"

    Write-Host "Successfully retrieved $($ServicePrincipalObjects.count) service principal objects and their owners"

}

catch {

    Throw "Error retrieving service principal objects: $_"

}

# Get all application objects with their owners expanded

try {

    $ApplicationObjects = Get-MgGraphPaged -Endpoint

"applications?`$expand=owners"

    Write-Host "Successfully retrieved $($ApplicationObjects.count)

application objects and their owners"

}

catch {

    Throw "Error retrieving application objects: $_"

}

# Define an array to hold the results

$Results = @()

# Combine both service principals and applications into a single collection for processing

$Combined = @(

    $ServicePrincipalObjects |

    Where-Object { $_.owners } |

    ForEach-Object { [PSCustomObject]@{ Type = 'ServicePrincipal'; Object = $_ } }

 

    $ApplicationObjects |

    Where-Object { $_.owners } |

    ForEach-Object { [PSCustomObject]@{ Type = 'Application'; Object = $_ } }

)

 

# Process each object to extract required properties and resolve owner display names

foreach ($Item in $Combined) {

    $Object = $Item.Object

    if (-not $script:OwnerCache) { $script:OwnerCache = @{} }

    $Owners = (@($Object.owners) | ForEach-Object {

            $Id = $_.id

            $DisplayName = $_.displayName

            if ([string]::IsNullOrEmpty($DisplayName)) {

                if ($script:OwnerCache.ContainsKey($Id)) {

                    $DisplayName = $script:OwnerCache[$Id]

                }

                else {

                    try {

                        $Resp = Invoke-MgGraphRequest -Method GET -Uri

"https://graph.microsoft.com/v1.0/directoryObjects/$Id`?$select=displayName" -

ContentType 'application/json'

                        $DisplayName = $Resp.displayName

                    }

                    catch {

                        $DisplayName = $null

                    }

                    if ([string]::IsNullOrEmpty($DisplayName)) { $DisplayName

= $Id }

                    $script:OwnerCache[$Id] = $DisplayName

                }

            }

            "$DisplayName ($Id)"

        }) -join '; '

 

    $Results += [PSCustomObject]@{

        ObjectType  = $Item.Type

        AppId       = $Object.appId

        ObjectId    = $Object.id

        DisplayName = $Object.displayName

        Owners      = $Owners

    }

}

# Export results to CSV

$Results | Export-Csv -Path ".\ApplicationOwners_ServicePrincipalOwners.csv" -

NoTypeInformation -Encoding UTF8

Write-Host "Exported $($Results.count) entries to

ApplicationOwners_ServicePrincipalOwners.csv"

 

 

What’s next?

In Part 2, we’ll explore safer alternatives to assigning ownership on application and service principal objects in Entra ID. We’ll also look at common scenarios where ownership is assigned today, such as managing credential expiry, and provide practical guidance on how to handle these cases securely.

Bookmark this article or subscribe to the AppGov Score blog to be notified when it’s published.

Stay tuned!

Share This:

Glenn Van Rymenant

Written by Glenn Van Rymenant

Glenn Van Rymenant is an independent Microsoft 365 consultant and identity security specialist with hands-on experience designing, implementing, and managing secure and compliant Microsoft environments. He focuses on identity and access management and PowerShell automation, with strong expertise across the broader Microsoft 365 platform.