Understanding Entra ID App Registrations, Enterprise Applications and Service Principals Part 2

In this blog post, I'm going to talk about what Enterprise Applications and Service Principals are and how they differ from App Registrations again.

At the end of 2024, I wrote the article Understanding Microsoft Entra ID App Registrations, Enterprise Apps and Service Principals which has quickly become one of my most read articles. Today I want to revisit that topic and reiterate on some of the things it covers. Especially since it seems like there is still a lot of confusion around the terminology and definitions of App registrations, Enterprise Applications and Service Principals.

What are App Registrations

This one is actually pretty easy to explain. Unlike in my original article, I’ll try to keep it shorter this time. An App registration is the application object that gets registered in Entra ID. The portal lists your registered apps as App registrations and essentially transforms the verb of registering an application to a noun. An app registration is an application that has been registered in Entra ID.

The application part of app registrations only refer to the part of an application that is integrating it in Entra ID. It’s by no means a full-fledged app that can be installed, executed or accessed through a browser. Creating app registrations for use with unattended scripts is a totally valid use case as well. In that case, there is only a script but no real application. The script still needs an app registration and a service principal to authenticate and access resources like Microsoft Graph.

Apps can be registered as single or multi tenant. This is called sign-in audience. When you register an app yourself, the application object (app registration) will be created in your tenant. When you add a multi-tenant app owned by someone else to your tenant, like i.e. Zoom, you’re adding a service principal for Zoom to your tenant, which will then show up under Enterprise applications in your tenant.

In that case, Zoom owns the app registration and they’ve registered the app as a multi-tenant app. The app registrations serves as a blueprint and includes the required permissions, for which you’ll be asked for consent, when you add the app (a service principal for the multi-tenant app) to your tenant.

Enterprise Applications and Service Principals

There are numerous blogs out there which claim that they are not the same thing. They’re wrong. Enterprise applications are pseudo objects. There is no such thing as an Enterprise application object in Entra ID. That becomes abundantly clear when you go beyond the portal and start working with Microsoft Graph. I’m going to talk about that later on

Nothing beats a good old OG meme…

You could say that all Enterprise applications are service principals but not all service principals are Enterprise applications. Basically, enterprise applications only describe one specific type of service principals. Only service principals for which an app registration either exists in your or in another tenant are considered enterprise applications.

I totally get why people get confused here since the Entra ID portal does a bad job clearly labelling things.

The entire menu in Entra ID is called Enterprise applications but the default view in that menu defaults to a specific filter also called Enterprise Applications.

Enterprise applications Menu default filter

The Enterprise applications view lists all service principals for which an app registration exists either in your or in another tenant. However, it doesn’t list all your service principals.

When you change the filter to Managed identities, the menu title still says Enterprise applications even though the menu is now displaying managed identities only. Managed identities are a type of service principal. Remember, that technically, there is no such thing as an Enterprise application object in Entra ID. It’s just the name of the menu and the default filter that only shows apps for which an app registration exists in any tenant.

Enterprise applications Menu with Managed identities filter

Even when you view a managed identity in detail, it still says Enterprise Application in the top right corner of the managed identity service principal object.

Managed identity detail view

Managed identities do have an application ID but there is no app registration object in your tenant. Since managed identities, including their certificates are managed by Microsoft, I’m assuming that there is an app registration in some Microsoft managed tenant somewhere but that is just an assumption.

Enterprise applications == Service Principals

Proof No. 1 - Documentation

Luckily, it looks like Microsoft is acknowledging the problem around the terminology and starts to rectify this a bit by updating their documentation. This Microsoft Learn article includes a lot of helpful information on the topic.

In the Entra ID portal, you’re always going to see App registrations and Enterprise application menus. But when you look at the learn article linked above, you’ll see that they only mention Application and Service principal objects in the titles.

In fact, when you search the page for Enterprise application you’ll only get one hit. (At the time of writing this article.)

You can use the Enterprise applications page in the Microsoft Entra admin center to list and manage the service principals in a tenant. You can see the service principal’s permissions, user consented permissions, which users have done that consent, sign in information, and more.

― Microsoft Learn

There is also a video embedded on that page:

Screenshot of the video that appears to be offline now.

I transcribed the first part of the video:

App registrations and service principals are the backbone of secure application management. In the Microsoft Entra Admin Center, App registrations are listed as such and represent your app on a global scale across all tenants. Conversely, service principals are listed as enterprise apps and they represent your app within a specific tenant.

― Microsoft Learn

Here’s another learn article that states:

Users can perform the following actions on owned enterprise applications. An enterprise application consists of a service principal, one or more application policies, and sometimes an application object in the same tenant as the service principal.

― Microsoft Learn

And here’s another one titled Properties of an enterprise application.

This ID is the unique identifier of the service principal object associated with the application. This identifier can be useful when performing management operations against this application using PowerShell or other programmatic interfaces. This identifier is different than the identifier for the application object.

The identifier is used to update information for the local instance of the application, such as assigning users and groups to the application. The identifier can also be used to update the properties of the enterprise application or to configure single-sign on.

― Microsoft Learn

While these two still kind of let you believe that Enterprise applications are a form of Entra ID objects, they at least mention the term service principal alongside enterprise application.

Proof No. 3 - Entra ID Portal

I’m not sure if you’ll let me count the portal as proof that Enterprise applications are in fact service principals since I already said that the portal does it wrong in most places. Anyway, if you only create an app registration and don’t add a service principal for it, the app registration overview will include a link to Create Service Principal.

App registration without a service principal App registration with service principal

When you click on that link to Create Service Principal, it directly takes you to the newly created service principal object but since this is Entra ID, it will still say Enterprise Application at the top of the page.

Under properties of an Enterprise application the tool tip for Object ID also clearly states that this is service principal object.

Tool tip for Service Principal Object ID

Proof No. 4 - Microsoft Graph

All Microsoft Graph Functions, Cmdlets and endpoints are called *MgApplication* for app registration and *MgServicePrincipal* for service principal related management operations. You can check for yourself by running Get-Command *EnterpriseApplication* in PowerShell. You’ll get zero results.

Here are some more Microsoft learn links that mention enterprise application in their title but the Microsoft Graph commands are all for service principals.

At the beginning, I mentioned some blogs claiming that Enterprise applications and service principals are not quite the same things. It’s usually not my style to call other people out but I’ve had so many discussions about this already that at this point, facts are all that matter to me.

Of course I’m not saying that I’m the only one understanding the topic. There are other great blogs out there which nail it. Here are two examples:

Now this one is one I have a problem with.

An Enterprise Application is essentially a Service Principal with additional configurations specific to your tenant. It is created after the App Registration process but exists within your tenant’s context. The Enterprise Application object manages how the application is used within the organization, including SSO configurations, user and group assignments, and conditional access policies.

― C-Nunnets on Medium

So far, so good. That’s all correct. However, further down in the FAQ they state this:

Q: Are Service Principals and Enterprise Applications the same thing? A: Not quite. A Service Principal is an application’s identity to act within EntraID. An Enterprise Application is essentially a Service Principal with extra configurations specific to your tenant, such as user assignments and access policies.

Q: Why do I need all three? Can’t I have one? A: You need all three for a complete application lifecycle in EntraID. You register the app for its basic identity, the Service Principal provides the means for the app to act, and the Enterprise Application manages how it is used within your organization.

― C-Nunnets on Medium

These statements are not entirely wrong but they’re also not a quite correct. Saying that you need all three things when in reality there are only two kind of objects is just wrong. All the properties, such user and group assignments (who is allowed to use the app) are readable and writeable on service principal objects in Microsoft Graph. There are no settings exclusive to the Enterprise applications menu in Entra ID.

Users and groups of the service principal shown in Enterprise applications menu Same user returned in Microsoft Graph for the same service principal

As you can see, the same properties you see in the portal’s Enterprise applications section are also available in Microsoft Graph on service principal objects.

Proof No. 5 - Microsoft Employees

To be absolutely sure, I asked the question if Enterprise applications are real Entra ID objects or if they are essentially just a fancy term for service principals to two different Microsoft employees independently. One of them has a weekly newsletter about Entra ID and the other one actively contributes to application identity related documentation on Microsoft Learn. They both confirmed to me that there is no such thing as an enterprise application object in Entra ID and if you boil it down, all enterprise applications are service principals.

Other Myths about App Registrations and Service Principals

While I’m at it, I might as well just keep going and clear up some other myths about app registrations and service principals…

Acting Identity in App Only Auth Sessions

By now it should be clear, that you need both an app registration and a service principal to authenticate and perform actions against Microsoft Graph. You can’t have a service principal without an app registration. Keep in mind, that for multi-tenant apps, you won’t see the app registration in your tenant but it must definitely exist in another tenant. I covered what happens when a multi-tenant app registration is deleted from a 3rd party tenant here.

Because service principals are basically spawned off app registrations, it’s theoretically possible to only have an app registration but no service principal. However, you won’t be able to do anything until you also have a service principal. I already covered that in detail in my first blog post about this topic.

There is one scenario in which you actually want to have only an app registration but no service principal in your tenant. I’ll talk about that later.

Let’s go over all the different Ids of app registrations and service principals before I actually establish a session using the Microsoft Graph Command Line Tools (Graph PowerShell SDK).

App Registration IDs

An app registration has two Ids: an Application (client) ID and an Object ID. If you want to learn more about what a client is in OAuth, I suggest reading this and this blog post and watch this video. By the way, at 26:52 John Savill also confirms that the Enterprise applications menu in Entra ID is enumerating your service principals.

Application (client) ID and Object ID on an app App registration

The application (client) ID is the globally unique (across all Entra tenants) ID of your application. This is used when you want to establish a session to Microsoft Graph from PowerShell or other applications.

Here’s where it gets confusing again. When you use PowerShell to retrieve an application object (app registration) you must enter the app’s Object ID for the -ApplicationId parameter.

Using the Application (client) ID from portal fails Using the Object ID as param value for ApplicationId works

If you want to retrieve your application object by application (client) ID you need to use a filter:

1
Get-MgApplication -Filter "AppId eq 'bfdc4320-01d3-4cb0-b033-03ddbe5125d5'"

Service Principal IDs

Now let’s look at the IDs of service principals. A service principal has an Application ID and an Object ID. The Application ID is always the same as the Application (client) ID of the app registration it’s derived of. That is the case for both multi-tenant apps (like Zoom etc.) you’ve added to your tenant as well as apps you’ve registered in your tenant yourself.

Service Principal IDs

When you want to retrieve a service principal with PowerShell, you do that also by passing its Object ID for the param value of ServicePrincipalId.

Get-MgServicePrincipal using the Object ID

To retrieve a service principal for an app ID (client ID), you must also use a filter:

1
Get-MgServicePrincipal -Filter "AppId eq 'bfdc4320-01d3-4cb0-b033-03ddbe5125d5'"

In both cases, you must use the object ID to retrieve the object, which kind of makes sense if you compare it to other object related commands in the Microsoft ecosystem. What doesn’t really make sense is that the param for Get-MgApplication is called -ApplicationId when we generally refer to an app’s client ID as the app/application ID but the param expects the object ID. In my opinion something like -ApplicationObjectId would have made more sense here.

Establishing an App Only Auth Session

Once signed in, Get-MgContext will show your client ID but there’s absolutely no mention of the service principal ID being used in that session.

Client ID in Graph Context

So what’s the acting identity, is it the app registration or the service principal?

There’s the fact that client secrets and certificates are configured on app registrations and not on service principals directly. On the other hand, a service principal literally includes the word principal, as in security principal in its name.

Luckily, I also have a blog post about how to get an access token of an already established Graph PowerShell session.

So I inspected the token claims:

Claims included in the access token

The token claims clearly list the object ID as value of the service principal for oid alongside the app ID in app_id. I already covered that the sign-in logs only list service principal ids but no application ids in my first blog so this makes sense.

If I compare this against a token of a delegated session, where a user signed in using their credentials, we can see the the oid is the user’s object ID.

Graph Context of Delegated Session with User ID Token claims of delegated session listing user ID as oid

I think it’s safe to say that we all agree that in a delegated session, the authenticated user is the acting principal. In that case the oid is the user’s ID whereas in an app only auth session the oid is the object ID of the service principal. This makes the service principal the acting identity and not the app registration.

There’s also the fact that in multi-tenant scenarios, your tenant won’t have an app registration object if you’re using a 3rd party app. You can’t use something to sign in, if you don’t have an object for it in the first place.

Testing against a Service Principal’s Own Object

I took this even further and made another test. I created an app registration and a service principal and didn’t grant any permissions to it. Why? Because security principals without permissions can usually only read and update their own object. I wanted to see if the service principal will be able to update only the service principal object or also the app registration object.

This screenshot shows that there are no roles listed between rh and sub if you compare it to the one above.

Token claims do not include any roles at all

Even with no permissions at all, I’m still able to read both the app registration and service principal object of the app I used to sign in. I can’t however, read any other objects.

Get-MgApplication Get-MgServicePrincipal

Since I’m able to read both the application and service principal object, it doesn’t prove that the service principal is the acting identity yet.

Next, I tried updating the display name of both objects. Both failed with 403 forbidden. I can only assume that this is because the service principal inherits its display name from the app registration object but since the service principal is the acting identity, it’s not allowed to update the app registration object. In other words, the app registration object is not the same object as the signed in, acting identity.

Update-MgApplication and Update-MgServicePrincipal both fail

I then looked for a property which is unique to both objects and identified the Owners property as a good test subject. Owners on app registration and service principal objects are different.

Test adding an owner to the service principal and the app registration

The signed in service principal was allowed to add owners to its own object but was denied adding an owner to its associated app registration.

Just to be absolutely sure, I tested adding an owner to a different service principal. As expected, this failed.

Test adding an owner to a different service principal

The Ultimate and Final Test

Just like user accounts, service principals can be disabled. This can be done from a service principal’s properties in the portal or through Graph PowerShell.

Disabling a Service Principal in the Entra ID portal

The equivalent in PowerShell is:

1
Update-MgServicePrincipal -ServicePrincipalId d1e8a817-57e9-4369-a31e-3ef01c673607 -AccountEnabled:$false

I disabled the service principal but didn’t sign out of the established session in PowerShell. When I tried to run a command that worked before again, I got the following error message: The authenticating application principal is disabled.

Error message for disabled Service Principal

And after some time, the token became invalid.

Invalid Token error message

All of this definitely proves that a service principal and not an app registration is the acting identity in an app only auth session. This also ties in to the next topic: are permissions granted to app registrations or service principals?

Required Permissions vs Granted Permissions

I already covered permissions quite a bit in my original post. This time I’m trying to shed some light on what is happening when you configure permissions on an app registration and grant consent.

First of all, permissions are not granted to app registrations. They wouldn’t be of any use to them anyway, since I’ve just proven that service principals are the identities which act against Microsoft Graph and other resources.

Again, I totally understand why you’d think that permissions are granted to app registrations because of what the portal is doing. But I’m going to show you why that’s not the case.

We already know that there’s different types of service principals. Service principals which have been created for an associated app registration are of type Application. You can check this by running the following command:

1
2
3
4
5
6
7
Get-MgServicePrincipal -ServicePrincipalId 37b5562c-7c23-46a8-ac32-5ca4d96dc485 | fl DisplayName, ID, AppId, ServicePrincipalType

# Output
DisplayName          : AdminUnitScopedServicePrincipal
ID                   : 37b5562c-7c23-46a8-ac32-5ca4d96dc485
AppId                : bfdc4320-01d3-4cb0-b033-03ddbe5125d5
ServicePrincipalType : Application

And here’s an example of a managed identity:

1
2
3
4
5
6
7
Get-MgServicePrincipal -ServicePrincipalId 08c3773a-83ca-4441-a6d4-35d3bb0bf274 | fl DisplayName, ID, AppId, ServicePrincipalType

# Output
DisplayName          : mzz-automation-account-012
ID                   : 08c3773a-83ca-4441-a6d4-35d3bb0bf274
AppId                : 0dcc5d4a-74c0-4f04-88cc-420a7539166e
ServicePrincipalType : ManagedIdentity

Managed identities still have an app ID but there is no app registration object in your tenant for them. If permissions where granted to app registrations, managed identities simply wouldn’t work.

This is basically what people mean when they say that app registrations serve as a template or a blueprint for the service principals. On app registrations, developers configure (define) what permissions their app needs in order for it to function properly in your tenant.

App registrations and configured permissions greatly simplify application management for tenant admins and owners of multi-tenant SaaS apps. You can create a service principal for an app like Zoom and grant all required permissions with a single click during the consent process.

If app registrations didn’t offer this functionality, developers would need to create long and complicated guides to explain to their customers what permissions a customer needs to add manually for their app to work in a customer’s tenant.

In fact, it’s not even possible to grant permissions to a service principal from the portal. There is no button to add permissions here. You can only do it from an app registration. To learn about all the ways in which permissions can be added, see this.

Permission on service principal in Entra ID: No add a permission button Permissions on app registration in Entra ID: Add a permission button available

If you want to, you can grant permissions directly to a service principal through PowerShell or by using the CLI for M365.

Using the CLI for M365 is actually a lot easier than using Graph PowerShell in this case. Here’s an example on how to add a bunch of Graph permissions to a service principal:

1
2
3
4
# M365 CLI login
m365 login --appId $appId --tenant $tenantId --authType browser

m365 entra approleassignment add --appObjectId $servicePrincipalObjectId --resource "Microsoft Graph" --scopes "Application.Read.All,Sites.Selected,User.Read.All,CrossTenantInformation.ReadBasic.All"

Now I’m not going to lie, this is confusing to me as well. The param is called --appObjectId and the description says: Application objectId of the App Registration to which the configured scopes (app roles) should be applied.

This doesn’t add up as I’m able to assign new permissions to a managed identity using it’s service principal object ID but not its application ID. It’s the same for an application service principal. The only ID that the above command works with is the service principal’s object ID. And unlike the param description, that makes total sense. (I’m going to reach out to the CLI for M365 team and ask for clarification.)

I’ve added the Directory.ReadWrite.All Graph permission to a service principal now using the CLI for M365. You can see that it’s now granted to the service principal in the screenshot below.

Permissions granted to the service principal

Now if I switch to this service principal’s app registration, you can see that permissions are split up between Configured permissions and Other permissions granted. And just because permissions are configured, it doesn’t mean they’ve been granted as well. Permissions that actually have been granted to the service principal feature a green check.

Permissions on the app registration

ChatMessage.Read.All hasn’t been granted yet. If you go back to the screenshot of the service principal permissions, you can see that it’s not available there. This means that it can’t be used before consent is granted.

Other permissions granted list permissions which have been granted to the service principal directly. Ideally, your apps will never look like this because keeping configured and granted permissions in sync is one of the main purposes of app registrations.

The property that represents what the portal displays as configured permissions is called RequiredResourceAccess in Graph objects.

Required Resource Access in Graph PowerShell output

This can be verified by using the browser dev tools as well. When the an app registration’s permissions page is loaded, it first gets the app registration by app ID from https://graph.microsoft.com/beta/myorganization/applications(appId='bfdc4320-01d3-4cb0-b033-03ddbe5125d5'). The response then lists the configured permissions under requiredResourceAccess regardless of if the permissions have already been granted to the service principal.

Required Resource Access part in web response

Delegated permissions are listed as Scope and application permissions are called Role. In the Microsoft Graph Permission Reference we can see that the ID of ChatMessage.Read.All is b9bb2381-47a4-46cd-aafb-00cb12f68504 which is part of the required resource access even though it hasn’t been granted the the service principal yet. You can read more about application and delegated permissions here.

If we check the ID of a permission which is listed under Other permissions granted, for example Directory.ReadWrite.All (19dbc75e-c2e2-444c-a770-ec69d8559fc7) we can see that it’s not part of the required resource access property.

Let’s check the next request in the browser dev tools. This goes to https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq 'bfdc4320-01d3-4cb0-b033-03ddbe5125d5'. This endpoint does not return app role assignments (granted application permissions) or scopes (granted delegated permissions). It’s simply performed to find the service principal object ID by filtering service principals for a matching app (client) ID (the one of the current app registration).

Finally, the portal is requesting the app role assignments (application permissions) and OAuth 2 permission grants (delegated permissions) for the current service principal ID using these requests:

https://graph.microsoft.com/v1.0/servicePrincipals/37b5562c-7c23-46a8-ac32-5ca4d96dc485/appRoleAssignments?$top=999

Response including application permissions granted to the service principal

The second last permission in the screenshot (19dbc75e-c2e2-444c-a770-ec69d8559fc7) is Directory.ReadWrite.All.

The second request shows the granted delegated permissions.

https://graph.microsoft.com/v1.0/oauth2PermissionGrants?$filter=clientId%20eq%20%2737b5562c-7c23-46a8-ac32-5ca4d96dc485%27%20and%20consentType%20eq%20%27AllPrincipals%27&$top=999

Response including delegated permissions granted to the service principal

So, earlier I established that service principals are the acting identities in authenticated sessions and this proves that permissions are granted to service principals and not app registrations. App registrations merely define what permissions a service principal should have for the app to function properly.

The problem is that the portal tricks you into believing that permissions are granted to app registrations because in the portal, granting permissions is only possible through the app registration menu. But behind the scenes permissions are granted to an app’s service principal when you grant admin consent to new permissions.

I wasn’t able to fully trace what happens when you grant consent to a permission on an app registration in the browser dev tools but I was able to do it for when you revoke admin consent for a permission.

In that case, a DELETE request including the app role ID and the service principal by object ID is sent to https://graph.microsoft.com/v1.0/servicePrincipals/37b5562c-7c23-46a8-ac32-5ca4d96dc485/appRoleAssignments/LFa1NyN8qEasMlyk2W3EhSrSirfW4XtPjJPVuu_KHX0.

The app role ID is only present on the service principal’s app role assignments and not on the app registration. An app registration simply doesn’t hold any privileges, roles or permissions despite the way it’s presented in the portal. This was also confirmed to me by the aforementioned Microsoft employees.

Adding Admin Roles to Service Principals

Not only Graph permissions can be assigned to service principals. It’s also possible to assign administrative roles, such as Groups Administrator to a service principal. Even in this case, Entra ID doesn’t make it easy for us to understand. When you add a role assignment to a service principal, the search result will list a service principal’s application ID instead of the object ID. To make it extra confusing, it will even list managed identities as Enterprise applications.

Detials shows the app ID of a service principal instead of the object ID Managed identity properties

After the role assignment has been added to the service principal, it still shows the app ID as user name but it does say ServicePrincipal under Type. Managed identities do have an app ID but there is no app registration object in the tenant.

Administrative role assignment for a service principal

Another peek into the browser dev tools also confirms that it’s returning the service principal object. (This is also the case for service principals for which an app registration object does exist in the same tenant.)

Service principal object in web response Service principal object in web response

While the portal lists the app ID, the web request to the role assignments endpoint clearly returns Microsoft.DirectoryServices.ServicePrincipal as principal value and also features the service principal object ID. For comparison, a user role assignment’s principal is listed as Microsoft.DirectoryServices.User.

Why Would you have an App Registration Only?

I’m not sure how common this misconception is but I want to talk about it anyway. Earlier I said that there is one scenario in which you might want to have an app registration only. That is when you’re the publisher of a multi-tenant app and you’re either using a dedicated tenant for the app registration or you don’t actually need to access any resources in the tenant where your app is registered.

Most publishers of SaaS apps likely also use their own product but some companies choose to register their applications in a dedicated tenant which is only used to host the app registration and maybe some Azure resources. If I was building a SaaS app, I wouldn’t stick my app registration into the same tenant that’s used for daily business. I’d add the app as an external app to my internal operations tenant the same way as any customer would add the app.

When I started dealing with app registrations, I always assumed that you need to grant admin consent in any case and that all the checks must be green in order for customers to be able to use the app. That’s not the case.

A service principal only needs to have permissions granted or even needs to be created in each tenant where the app is being used. If I’m the provider of a multi-tenant app and I only want my app to access the data of my customers and don’t use the app myself in the tenant where the app registration lives, I don’t need to grant any permissions. In fact, I don’t even need a service principal for it in that tenant.

As you can see, I only have a multi-tenant app registration but no service principal in the tenant where the app is registered. My app needs the User.Read.All application permission but since there is no service principal for it in my tenant, the permission hasn’t been granted. (Granting consent would create the service principal automatically). Finally, the app has a client secret to connect to Microsoft Graph without a signed in user.

App registration in service tenant Configured permissions of app registration Client secret on app registration

I’ve added the app to another test tenant of mine. (This would be a customer tenant.)

Multi-tenant app in customer tenant

Now as the app owner, I can connect to the customer tenant using their tenant ID and the client ID of my registered app:

1
2
3
4
5
$tenantId = Read-Host -Prompt "Enter the tenant ID"

$credentials = Get-Credential -Message "Enter the application (client) ID and secret"

Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $credentials -NoWelcome

Since I’m passing both the Tenant ID and the App ID in Connect-MgGraph, I can now access the resources in the customer tenant using the service principal that was created in the customer tenant, when the customer added the app by granting admin consent.

At first I thought it was weird that the application (client) ID is used for sign in, when the token is issued for the app’s service principal but after this test, it makes perfect sense.

When both the app registration and a service principal exist in the same tenant (like with any single-tenant app), it’s easy to find the service principal ID. But when I look at this from a multi-tenant perspective, it becomes clear that I can’t possibly know the service principal object ids of all the tenants my app has been added to. And the sign in process/command would need to be unique for each tenant (different service principal ID).

But by providing the tenant ID and the app ID during sing in, the correct service principal object ID can be determined by the target tenant and a token for it is issued.

So, here you can see that I’m now able to use the User.Read.All application permission which the customer tenant has granted consent to, to query a user from another tenant even though the tenant where the app is registered doesn’t even have any granted permissions or let alone a service principal object.

Proof that no service principal is needed in app owner’s tenant

Summary

App registrations and service principals remain an extremely complex topic. I generally think it’s a good idea to stick to facts and technical terms. Frankly, I’m not sure how that will work out in this case as the term Enterprise applications is all over the place in Entra ID but not once mentioned in Graph/PowerShell.

I guess I don’t really care whether we call them Enterprise applications or service principals as long as we’re aware of the following key takeaways:

Enterprise applications is just a term for service principals which are associated with application objects (app registrations). All Enterprise applications are service principals but not all service principals types are considered Enterprise applications as well.

Enterprise apps sometimes also describe multi-tenant apps for which the app registration lives in another tenant (i.e. Zoom etc.). However, that doesn’t bode too well with me either since the Enterprise applications menu in Entra ID also lists all service principals of the apps for which an app registration exists in the same tenant.

In app only auth scenarios, service principals are the acting identity and permissions are always granted to service principals and not to app registrations.

I hope that this blog provided new insights and answers to some of the questions you might have had. Gathering all of this information and proof was quite fun but also very time intensive. If you appreciate the effort, feel free to buy me a coffee.

At this point I’d also like to thank all the people who already bought me a coffee after reading my original article.

What’s Next?

I think most of the problems outlined in this blog post are owed to the fact that Entra ID uses two separate menus (App registrations and Enterprise applications) to manage the different types of objects, even though they’re closely related.

Each app registration and service principal share two (visible and obvious) things: the application (client) ID and the application name. This got me thinking… what if we stop thinking about them as two separate things but rather start thinking of them as one app consisting of different objects.

Wouldn’t it be great to see only an app’s name and ID but instantly know what kind of objects exist for any app in my tenant? Do I have an app registration and a service principal or is it an external app owned by someone else, in which case I only have a service principal?

Over the past couple of weeks, I’ve been prototyping an Azure runbook that leverages the Graph API to gather and combine all the relevant information to then update a SharePoint list on a schedule. This gives me a single pane of glass type of thing where I can see all my apps, including all important properties.

The list allows me to do all kinds of cool stuff like creating pre-built filters in different views but also offers great search and filtering capabilities. For example, I can search for any Graph permission and immediately see any apps that have that exact permission.

I’ll be sharing more information and the code to build this yourself over the next couple of months. Here’s a sneak peek of it:

Sneak peek of Unified Entra Apps View in a SharePoint list

Stay tuned!

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Hosted on GitHub Pages
Built with Hugo
Theme Stack designed by Jimmy