Understanding Microsoft Entra ID App Registrations, Enterprise Apps and Service Principals

In this (very long) blog post, I'm explaining everything you need to know about Entra ID applications, app registrations, enterprise apps and service principals from the view of a system engineer (not from a developer's perspective).

Intro

I once read a joke on X which I just vaguely remembered. Somebody was looking for a job in IT and the person hiring was like:

If you can tell me the difference between an Entra app registration and an enterprise app, I’ll hire you.

― Some guy on X

If you’re a seasoned developer, you might already know all of this but if you’re a systems administrator coming from a more traditional world, like I am, much of the stuff I’m covering today might be new, confusing, overwhelming or all the above to you. But rest assured, I didn’t fully understand it either until today.

I want to highlight that identity isn’t my primary focus, but it was still very important to me to understand all aspects of Entra applications. Most of the blog posts that already exist about Entra applications are written by professional developers and just assume that you’re already familiar with certain things. That’s what I’m trying to do differently with this article.

I’ll give you an example. Let’s say you need to change the usage location of an Entra ID user, and you want to do it with PowerShell. A couple of years ago, you could just install the AzureAD PowerShell module, log in with your account and get it done by running Set-AzureADUser -ObjectId user@domain.com -UsageLocation CH.

In today’s world you need to connect to Microsoft Graph using the Microsoft Graph PowerShell SDK (Microsoft.Graph.* PowerShell modules) and you need to make sure that the appropriate permissions have been granted to the enterprise app before you can do that, even if the account you’re using to sign in already has the permissions to do the same action in the Entra Admin Center.

In this particular example, I’m talking about what’s referred to as an enterprise app or an enterprise application. The name of the official enterprise app that’s used to access your tenant when using the Graph PowerShell modules is Microsoft Graph Command Line Tools.

Microsoft Graph Command Line Tools Enterprise Application

You can see that it says Enterprise Application below the name in the screenshot above. However, when you search for its Application ID, it lists the name under Enterprise Applications, but it also says Service Principal next to it.

Application ID search results

Because this app is owned and published by Microsoft, there’s no app registration for it in your tenant. You can only see the enterprise app. Only Microsoft can see the app registration in the tenant in which they registered the app (created the app registration).

Let’s recap this quickly. Microsoft created an app registration for the Microsoft Graph Command Line Tools and published it. Any Entra ID admin can now add this app to their tenant as an enterprise app and use it to connect to Microsoft Graph via PowerShell.

So, when I use Connect-MgGraph and don’t specify my own Client Id, I’m automatically signing in to Microsoft’s enterprise app.

Partial output of Get-MgContext

What’s the difference between an enterprise app and a service principal?

They are the same thing. Enterprise apps are just what they are called in the Entra Admin Center but they’re essentially service principals. The naming and UI elements here are very confusing. We already saw that searching for the app id in Entra Admin Center will say Service Principal next to the app but throughout this article, I’m going to show you more proof why every enterprise app is a service principal.

What’s a service principal then?

A service principal is always linked to an application (registration) either in your tenant or in another tenant. They inherit and share some of their properties, like the app id from their linked application. In essence, a service principal is an instance, or a child object, if you will, of a global application registered in Entra ID but it’s unique to your tenant. Even if another tenant owns the app, service principals will allow you to manage how and by which users the app will be used.

If you search for Service Principal in the global Entra Admin Center search box it will list Enterprise applications as the top result.

Entra Admin Center search results

What’s the difference between the application ID and the Object ID of an Enterprise App?

These are the descriptions when you click on the little (i) icons on an enterprise app in Entra Admin Center:

Application ID

This is the unique application ID of this application in your directory. You can use this application ID if you ever need help from Microsoft Support, or if you want to perform operations against this specific instance of the application using Microsoft Graph or PowerShell APIs.

― Entra Admin Center

The application id is the same in all tenants where the enterprise app has been added to.

Object ID

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

― Entra Admin Center

The object id is unique in every tenant to which the enterprise app has been added to. If an enterprise app is deleted and later added again, the object id will also change. The application id on the other hand is the same in every tenant because it’s derived of the application id of the registered app for which the service principal was created.

Adding an Enterprise App to Your Tenant

Providers/publishers of enterprise apps will typically give you a link which you have to open in order to grant admin consent on behalf of your organization. Granting admin consent will add the enterprise app to your tenant and requires global administrator rights.

In the case of the Microsoft Graph Command Line Tools, the enterprise app can be added simply by running Connect-MgGraph. This will open the browser and ask you for your consent.

Grant admin consent to add the enterprise app

I’ve just added the Microsoft Graph Command Line Tools enterprise app to a tenant where it didn’t exist before. If I check the audit log of the enterprise app, I can clearly see that there’s been an action for Add service principal even though the portal is calling it an enterprise application.

Enterprise application audit log Add service principal audit log details

Since it’s obvious that the same thing is sometimes called an enterprise app but sometimes it’s also called a service principal, I’ll try my best to stick to whatever the screenshots or code examples are calling it at the time. So, if the screenshot/code example is saying enterprise app, I’ll call it an enterprise app. If it’s saying service principal, I’m referring to it as a service principal as well.

I’m a Sys Admin, why should I care about all of this?

Let’s quickly go back to the example I used in the intro of this post. Let’s assume that all you want to do is to use PowerShell to change the usage location of a user. Why should you care about all of this? Why do you need an app for this? And what even is an app in this context? Is it an enterprise app or an app registration?

If you use the official Microsoft Graph Command Line Tools enterprise app, which you are when you run Connect-MgGraph without specifying your own -ClientId then you don’t need to worry about all this too much. All you need to do is to ask somebody with global admin permissions to add the enterprise app to your tenant and consent to the User.Write.All permission. That is, if you don’t have global admin rights yourself.

I purposely chose the Microsoft Graph Command Line Tools enterprise app for this example because a lot of Sys Admins will need that to do their job. The thing with PowerShell scripts is that there won’t always be something that’s graspable, something that can be referred to as an app. A script is not really an app, but it still needs an Entra application to sign into Microsoft Graph to do whatever it needs to do.

This is different from when we look at a real, graspable app like Zoom for example. In that case, we have the Zoom app (the Zoom client installed on a device). But we’ll also need to grant permissions the Zoom enterprise app to read/write the signed in user’s calendar information if users want to link their Exchange calendar to Zoom.

Example: Zoom enterprise app

The Zoom app and the Zoom enterprise app are definitely not the same thing even though both are called an app. Assigning the enterprise app to users won’t install Zoom on their devices. That’s what Intune is for.

So, as a Sys Admin, you might not be developing the next Zoom app that will be used by millions of people in thousands of Entra ID tenants, but you simply want to create a PowerShell script that changes the usage location of an Entra ID user.

The Microsoft Graph Command Line Tools enterprise app can only exist once in each tenant so if the entire IT staff of a company is using the same app to manage Entra ID, consented permissions can accumulate and spiral out of control rather quickly. There is a good article about that from Tony Redmond over at Practical 365.

If you want to avoid that, then you’ll need to create your own app to connect to Graph. This is where you’ll have to deal with app registrations.

What Are App Registrations?

Adding an enterprise app is only possible when an app registration already exists either in your own tenant or in an external one.

When I go to enterprise apps in Entra Admin Center and click on Create your own application and then select Register an application to integrate with Microsoft Entra ID (App you’re developing) and click Create nothing happens just yet. Instead, I’m redirected to the App registrations page.

Trying to create a new enterprise app… …will take you to App registrations

This means that there is no such thing as an enterprise app without an existing app registration. Not even in PowerShell. I’ll talk more about this later.

The Entra Admin Center specifically says App you’re developing but it could also be just a script that you’re developing.

Create an App Registration

In Entra Admin Center

App registrations can be found in the Entra Portal under Identity\Applications\App registrations. Enterprise applications are also found in the same menu, which is another reason why it’s so hard to differentiate between the two. As you can see in the screenshot below, there is no app registration for Microsoft Graph Command Line Tools in my tenant even though I’ve added the enterprise app before.

App registrations in Microsoft Entra Admin Center

An app registration is essentially exactly what the name says. It simply registers an app in Entra ID. When you create a new app registration, you’re basically just telling Entra ID that this app now exists but you can’t really do anything with the app registration alone.

An Entra app can be registered to be added to either a single tenant (the tenant in which you register it), Multitenant (any Entra ID tenant) or Multitenant + personal Microsoft Accounts which are used for sign-ins with Microsoft 365 Family/Outlook.com/Skype/Xbox etc.

If you want to use this app to connect to Graph PowerShell in a script and you only need to manage your own tenant, making it available in your tenant only is the choice to go with. If you were in fact developing the next Zoom, you should choose to make it multi-tenant.

Here I’m creating a new single-tenant app registration called Graph PowerShell Demo (Created in Portal). If you want to sign into your app in Graph PowerShell, you also need to set the Redirect URI to Public client/native (mobile & desktop) and configure http://localhost as the redirect URI.

Register a new application

This is what you’ll see after the app registration has been created.

App registration after it’s been created in the portal

A very important part which is not often mentioned is that when you register a new app in the portal, an enterprise app (service principal) is automatically created for it as well.

When I search for the application (client) ID of the newly created app in Entra ID, two objects are returned. An app registration (application) and an enterprise application (service principal).

App registration and enterprise application in search results

We can also see this very clearly in the audit log. First the application (app registration) is added and immediately after that, the service principal (enterprise app) is added as well.

Audit log after creating a new app registration in the portal

In the details for the Add application activity the modified properties include a property named ServicePrincipalLockConfiguration which is a Json object and includes "IsEnabled": "true". I think that this is the part where the Entra Admin Center tells the provisioning backend to create a service principal for the app registration as well.

Add application log details

For the Add service principal activity we can see that the modified properties include the Application (client) ID as value for the ServicePrincipalName and TargetId.ServicePrincipalNames properties.

Add service principal log details

In PowerShell

To register a new app in PowerShell you have two options. You can either use the recently announced Microsoft.Graph.Entra module which is still in preview at the time of writing, or you can use the Cmdlet which is part of the Microsoft.Graph.Applications module.

With Entra PowerShell Module

Docs for New-EntraApplication

1
2
3
Connect-Entra -Scopes "Application.ReadWrite.All"
$appName = "Graph PowerShell Demo (Created with Entra PS)"
$newApp = New-EntraApplication -DisplayName $appName
With Microsoft Graph PowerShell

Docs for New-MgApplication

1
2
3
Connect-MgGraph -Scopes "Application.ReadWrite.All"
$appName = "Graph PowerShell Demo (Created with Graph PS)"
$newApp = New-MgApplication -DisplayName $appName

Both Cmdlets are called New-*Application but in the portal this action is called Register an application. The menu which lists applications in the portal is called App registrations but in PowerShell we use Get-EntraApplication or Get-MgApplication to retrieve registered apps.

As if this wasn’t confusing enough already, we now have to understand that what is presented to us as an app registration in the portal is sometimes also called just an application. When you create a new app registration, you’re creating a new application by registering it. The portal takes the verb registering and converts it into a noun by calling it an app registration.

The outcome of both the above examples is exactly the same. For the sake of simplicity, I’m only going to focus on Graph PowerShell Demo (Created with Entra PS) in this section.

As you can see below, when the app is created through PowerShell, no enterprise app is created automatically. Only the application is created (registered).

The enterprise app/service principal is missing

We have the audit log to back this up. It’s only showing an Add application action.

Audit log is only showing add application

Add a Service Principal with PowerShell

When you view the documentation for managing applications using the Entra PowerShell module, it becomes clear that registering an application and adding a service principal are two separate actions requiring different Cmdelts. There is absolutely no reference at all about enterprise apps on that Microsoft Learn page. They only talk about service principals.

To add a service principal for an app you registered using New-EntraApplication you’ll need to run this code to add a service principal for it:

1
New-EntraServicePrincipal -AppId $newApp.AppId

After this, you’ll see an app registration and an enterprise app when you search for the app id in the Entra Admin Center.

Enterprise app created with PowerShell

I told you earlier that you cannot create an enterprise app/service principal if no app has been registered for it before.

I tried to create a new service principal without specifying an app id anyway and I was immediately prompted for an AppId.

Prompt for required parameter -AppId

As expected, the documentation for NewEntraServicePrincipal lists the -AppId parameter as required. Funny enough, the docs for New-MgServicePrincipal say it’s not required but that’s definitely not the case.

Error details of New-MgServicePrincipal without -AppId

Connect to Graph PowerShell Using Your Own App

Now that I have an app registration and a service principal, I can use the application id to sign into Graph PowerShell.

1
2
3
$tenantId = "4bffbf87-53a0-4fce-b58b-4179cb3a3b7d"
$appId = "90b85c34-0c3f-4d69-9668-ea74f20e5d62"
Connect-MgGraph -NoWelcome -TenantId $tenantId -ClientId $appId

If I’m doing this for the first time, I’m prompted for admin consent. Note that you’ll need to specify the redirect URI either when creating the app registration through PowerShell or you’ll have to do it manually in the portal afterwards. Otherwise, this won’t work.

Admin consent request

Now you can see that I’m signed in using my own app and I’m not using the Microsoft Graph Command Line Tools app anymore.

Partial output of Get-MgContext

When I finally try to update a user’s usage location with an account that has global admin rights, I still get an error message because of insufficient privileges. This is because the User.ReadWrite.All permission is not part of the Scopes yet. I’ll show you how to add that later on.

Insufficient privileges

What if there is no Enterprise App/Service Principal Yet?

When you’re automating the registering of an app through a script, there’s no reason why you wouldn’t also create the service principal through the same PowerShell script but since this is a deep dive, I’m going to show you an alternative way anyway.

If an app registration is only telling Entra ID that an app exists, and no service principal exists for the app registration, will I still be able to sing in and use it?

The answer to this question is yes and no. Technically, you cannot use only an app registration to sign into the app. However, when you connect to Microsoft Graph and specify the -ClientId of an app registration that does not have a service principal yet, one is automatically created after you’ve granted admin consent.

Since I’ve already added a service principal for Graph PowerShell Demo (Created with Entra PS) with PowerShell, I’m going to demo this using the app called Graph PowerShell Demo (Created with Graph PS) which I’ve created with New-MgApplication.

This app currently only has an app registration but no enterprise app/service principal.

Graph PowerShell Demo (Created with Graph PS)

I did however add http://localhost as a redirect URI in the app registration through the portal after I’ve created the app with PowerShell.

Authentication page of the app registration

Now watch what happens when I sign into the app through Connect-MgGraph.

First of all, I need to grant consent for this app as well.

Admin consent request

After granting the consent I’m in.

Partial output of Get-MgContext

But how is that possible when there’s no service principal for this app registration yet? Well, this also triggered the creation of a new service principal, just like signing into Graph PowerShell using the Microsoft Graph Command Line Tools did.

The enterprise app/service principal was created after consent was granted.

And of course, this can also be seen in the audit log.

Audit log actions after signing into the app for the first time

Quickly Switch Between an App Registration and It’s Service Principal

When you’re managing apps and frequently need to switch between configuring the app registration and it’s enterprise app, the quickest way to do so is to open the API permissions menu on the app registration or the Permissions menu on the enterprise app.

When you’re viewing an app registration, there’s a link called Enterprise applications at the bottom of the browser window which will take you directly to the enterprise app of this app registration.

API permissions in an app registration

To get from an enterprise to its app registration (if it was registered in your tenant) you can click on the Application registration link in the middle of the browser window.

Permissions in enterprise app

Obviously, this part is missing from an enterprise app for which no app registration exists in your tenant.

Example: Microsoft Graph Command Line Tools

Quick Recap

If you’re still with me, I’d like to recap and elaborate on a couple of things. App registrations register an app in the Microsoft Entra Eco System. An application (client) ID of an app registration is unique across all Entra ID tenants. That’s documented here. Therefore, an app registration can only exist in one tenant.

An enterprise app is the same thing as a service principal. The Entra Admin center and other UI elements typically use the term enterprise application but Graph PowerShell and audit logs typically use the term service principal for them.

Enterprise apps can be added and exist in any tenant. If you register a new app in the Entra Admin Center, you’ll see both an app registration and an enterprise app for it in your tenant. Because they’re directly linked to each other, they always share the same display name and application id.

If you’re adding an enterprise app from a vendor, you won’t see an app registration in your tenant because the app was registered as a multi-tenant app in a different tenant.

When you create an app registration in the portal, a service principal is automatically added as well. When you create a new app registration through PowerShell you have to manually create a service principal for it.

App registrations are also called just applications and until a service principal is created for them, they don’t really do anything except telling Entra ID that the app exists and specifying what permissions should be requested when an enterprise app for the app registration is added. When signing into your app, the service principal is used.

Renaming Apps

Entra Admin Center will allow you to rename app registrations and enterprise apps. When you rename either one of them, the other one is automatically updated as well.

I first changed the name of the enterprise app by adding - Enterprise App to it, hoping this would result in different names to better distinguish between the app registration and the enterprise app. But this is not the case. In the audit log I can now see that both the service principal and the app registration were updated.

Service principal rename audit log App registration rename audit log

It’s the same case the other way around. When you change the name of an app registration, the enterprise app is renamed as well.

What about renaming a multi-tenant enterprise app? If I’m not the owner of the app/if the app hasn’t been registered in my tenant, it’s not possible to rename an enterprise app. Here’s the example of the Microsoft Graph Command Line Tools enterprise app again to demonstrate this.

The name is greyed out

​Some of the displayed properties that are not editable are managed on the application registration in the application’s home tenant.

― Entra Admin Center

To show you what happens to enterprise apps in other tenants, when you’re the owner of a multi-tenant app and you’re renaming the app registration, I must first create one.

Creating a Multi-Tenant App

As I’ve briefly explained before, the reason why you’d want to register a multi-tenant app is if you’re developing an app which will need to access data from customer tenants through Microsoft Graph. This could also be something much simpler though. For example, it could be a reporting solution which will access and process Teams call records from customer tenants.

It’s good practice to register multi-tenant apps in dedicated tenants. If you’re planning to develop an app which needs a registered Entra application, don’t create it in your main tenant you need for your internal day to day operations. Instead, create a dedicated service tenant which is only used to administer the resources needed for the app/service you’re developing/providing.

For this article, I’ll call the tenant in which I register the multi-tenant app the Service Tenant. After all, the call records I want to access are in my lab tenant and I want to show you how data in my lab tenant can be accessed from another tenant. So, if I registered the multi-tenant app in my lab tenant, I’d need another lab tenant with actual data in it. For this part, I’m going to call my lab tenant the Customer Tenant.

Note: Although the icons are very small, you can see which tenant I’m currently in by looking at the Edge profile icon (top left) or the user account icon (top right) in the screenshots.

This time, I’m creating a new app registration for a multi-tenant app and I’m doing this in the service tenant.

Register a new multi-tenant application

Because I used the portal to do this, this creates an app registration and an enterprise app in the service tenant.

I’ve added a couple of delegated permissions to this app now, but I didn’t grant admin consent in the service tenant.

Delegated permissions of multi-tenant app registration

Adding Multi-Tenant App to Another Tenant

To add the multi-tenant app to my customer tenant, I’m simply connecting to Microsoft Graph PowerShell using it’s app id and the tenant id of the customer tenant.

Connect-MgGraph to add multi-tenant app

Of course, I’ll have to grant consent for this as well.

Consent request dialog

After granting admin consent, the enterprise app has been added to my customer tenant, even though the app registration was created in the service tenant.

Enterprise app of multi-tenant app registration

In Permissions I can see that the enterprise app has the same permissions that were configured on the app registration in the service tenant.

Multi-tenant enterprise app permissions

Renaming a Multi-Tenant App

Now that I have a multi-tenant app, let’s revisit what happens when it’s renamed.

In the service tenant, I’ve now renamed the app from Graph PowerShell (Multi-Tenant) to Graph PowerShell (Multi-Tenant) V2. In my customer tenant, the name of the enterprise app/service principal was not updated, however, the name of the app was updated under properties.

Updated name in properties

When I check the Microsoft Graph context after signing in, I can also see the new app name. The tenant id is the one from my customer tenant.

Partial output of Get-MgContext

This is a great example to show that the app name and the app id of the enterprise app are in fact linked to the app registration of the service tenant but since the enterprise app is a unique instance with its own object id only present in the customer tenant, the enterprise app’s display name was not updated.

Am I using the Service Principal or the App registration to Sign In?

Wait, didn’t I say before that the service principal and not the app registration is used to sign into an app? So why does it show the new name of the app and not the unchanged name of the service principal in Microsoft Graph context?

This is very confusing indeed. But looking at this from a multi-tenant perspective should help clear things up. In the customer tenant, there is no app registration, only a service principal. How would I be able to sign into the customer tenant using the app registration, if it doesn’t exist in the customer tenant? It’s just not possible.

But let’s compare the app registration and the enterprise app in the service tenant again. By the way, here you can see that both the app registration and the enterprise app were renamed, just like when I renamed the single tenant app in my customer tenant.

App registration Enterprise app

Notice how there is no Activity section on the left navigation pane for the app registration. Sign-in logs are only available for the enterprise app. This is another fact which proves that the service principal is used for signing in.

Since I’ve never signed in to the app in the service tenant, the sign-in logs are empty there.

Empty sign-in logs in service tenant

In the customer tenant, the sign-in logs show two sign ins because I signed in again, after I changed the name of the app registration in the service tenant. The name of the enterprise app now says Graph PowerShell (Multi-Tenant) V2 because I’ve deleted the enterprise app and added it again, to test if it would be added with the new name. Since the log filter is set to application it will show sign in logs from both the old and the new service principal but in this particular example, the name of the application changed to V2 without deleting and adding the app again.

Sign-in logs in the customer tenant

As I’ve said before, the service principal object is created in the customer tenant, when the multi-tenant app is added. Therefore, the name of the service principal does not update when the app registration is renamed in the service (home) tenant but the name of the app that’s linked to this service principal does update in all tenants.

If the enterprise app is deleted from the customer tenant and added again, the enterprise app/service principal will be created with the new name of the app registration.

If you pay attention to the sign in logs of the enterprise app/service principal, you can see that that it filters for Application contains and it’s using the app id and not the object id of the service principal as value. I couldn’t find any reference of the service principal’s object id in the sign-in logs. The key is that the service principal is linked to the app registration by its application id. I think this is how Entra knows which service principal needs to be used.

Let’s turn to Microsoft Graph to see if I can find more information. To get the properties of the service principal, I need to specify the object id of the service principal because the app registration does not exist in the customer tenant.

1
2
$mgServicePrincipal = Get-MgServicePrincipal -ServicePrincipalId "e66c003a-c7e0-46c0-906a-4e30e0d85ab4"
$mgServicePrincipal | Format-List *name*, *id*, *princ*, *audience*

Partial output of Get-MgServicePrincipal

There are a couple of things to unwrap here. First of all, the AppOwnerOrganizationId includes the tenant id of the service tenant (tenant in which the application was registered). The Id of the service principal is what’s listed in Entra Admin Center as Object Id. I should probably mention again that I deleted the enterprise app and added it again, that’s why both names are the same now.

Both the AppId and the ServicePrincipalNames are set to the app id of the app registration in the service tenant. The portal doesn’t show you this, but I think that’s why you only see the app id but never the object id of the service principal.

I wouldn’t be me if I didn’t rename the app registration in the service tenant to Graph PowerShell (Multi-Tenant) V3 again after discovering this.

AppDisplayName and DisplayName are now different

This tells us that the AppDisplayName is the display name of the app registration which comes from the service (home) tenant. The DisplayName is the name of the enterprise app/service principal display name specific to the customer tenant.

In conclusion, you’re using the application to sign in, but you’ll need a service principal for the app to do so.

Control Who Can Sign Into Your App

Further proof that enterprise apps/service principals are used when signing in is that you define who can use/access your app on the enterprise app configuration page and not on the app registration. If you want to limit who can sign into your app, you need to enable Assignment required? and set this to Yes on the enterprise app’s Properties. In the screenshot below, I’m modifying the properties of the multi-tenant enterprise app which I’ve previously added to my customer tenant.

Set assignment required to yes

Under Users and groups I can now define which users and/or groups are allowed to sign into the app.

Users and groups configuration of enterprise app

When I try to sign in with a user which isn’t allowed under Users and groups I get an error message.

Error message when user doesn’t have the enterprise app assigned

If assignment required? is enabled, not even global admins can sign in, if they’re not explicitly allowed.

Permissions on Applications

As you may have noticed, there are permissions in both app registrations and enterprise apps. But what do they do?

Delegated vs Application Permissions

First, you need to understand the difference between delegated and application permissions. Delegated permissions require a signed in user and requests are made as the signed in user but the app which is used to connect to Graph has to have the appropriate delegated permissions.

For example, if you want to change the usage location of an Entra ID user via Graph PowerShell, your account needs to have the User Administrator role assigned and the app which you are using to connect to Graph needs to have the delegated permission User.Write.All configured and consented.

Just because your account can perform an action in the Entra Admin Center, it doesn’t mean that you’ll also be able to perform the same action in Graph PowerShell unless the delegated permission has been specifically configured on the app that you’re using to connect to Graph. Configuring something in the portal doesn’t require explicit permissions in addition to having an Entra Admin role assigned. But doing the same action through the Graph API requires an explicit permission on the app you want to use.

You should always follow the least privilege principle and only configure the permission that are actually needed. This link is a good reference to learn what each permission does. I also highly recommend checking all your existing applications which can access Graph via PowerShell and make sure that only admin users are allowed to sign into the apps.

Application permissions mean that an app will be able to perform actions without a signed in user. In this case, the action is performed as the app itself. You’ll need either a client secret or a certificate for that.

Add Permissions to Applications

Let’s look at different examples/scenarios.

You own the App Registration

In this example, I’m using the Graph PowerShell Demo (Created in Portal) app which was created in the customer tenant again. When the app registration is created through the portal, the delegated permission User.Read is added as a configured permission by default. Admin consent has not been granted yet and I’ve never signed into this app before. Thus, the permissions of the enterprise app are empty.

Configured permissions of app registration Permissions of enterprise app

When I click Grant admin consent on the enterprise app, a new browser window opens and asks me to consent to the permissions which are configured in the app registration. Signing into this app through Graph PowerShell for the first time would have the same effect.

Admin consent request

Let me add a new configured permission on the app registration.

User.Read.All added to configured permissions of app registration

I have not yet consented User.Read.All, that’s why it’s showing as Not granted.

When I sign into Graph PowerShell using the app id of this app, the scope is not added to the session.

User.Read.All scope is missing

I can grant admin consent for the added permission on the app registration from the portal.

Grant admin consent on app registration

When I connect to Graph again and check the context again, I can now see the User.Read.All scope.

Available scopes/permissions

The configured permissions of an app registration tell the enterprise app what permissions should be requested during the consent process.

Applications are authorized to call APIs when they are granted permissions by users/admins as part of the consent process. The list of configured permissions should include all the permissions the application needs.

― Entra Admin Center

When I check the permissions of the enterprise app, I can see that the User.Read.All permission was also added to the enterprise app.

Added permission on enterprise app

Add a permission without adding it configured permissions first

Although this isn’t following best practice, it’s also possible to add new permissions to the enterprise app without adding them to the app registration’s configured permissions first. To do so, I’m simply adding the scopes I want when I’m connecting to Graph PowerShell.

1
Connect-MgGraph -NoWelcome -TenantId $tenantId -ClientId $appId -Scopes "Group.Read.All"

Guess what happens now? Yep, I’m prompted to consent again.

New consent request dialog

When I check the permissions of the enterprise app, I can see that the Group.Read.All permission was added to it.

Enterprise app permissions

However, when I go back to the app registration, the freshly consented permission shows up under Other permissions granted and not under Configured permissions.

App registration permissions

Entra Admin Center says the following about this:

These permissions have been granted for NoCapTech but aren’t in the configured permissions list. If your application requires these permissions, you should consider adding them to the configured permissions list.

― Entra Admin Center

If a permission is required for your app, you can use the three dots to add other permissions to the app’s configured permissions.

Add other permissions to configured permissions of app registration

Remove Permissions

Let’s not forget that we’re still on a mission to change a user’s usage location using PowerShell. The Users.Read.All permission won’t help us here because it doesn’t include write permission. Let’s remove that one and add Users.Write.All.

I can either remove a permission or only revoke its admin consent. In this case I want to remove it entirely, so I must first remove it and then revoke the admin consent.

Remove permission from app registration Revoke admin consent for permission

Now I’m going to add the Users.ReadWrite.All permission and grant admin consent for it.

Add permission Grant admin consent

Because I’ve added this permission to the configured permissions, the next time I’m signing into Graph PowerShell using this app id, the permission will be available by default.

Partial output of Get-MgContext

This means that I’m now finally able to update a user’s usage location using PowerShell.

No more error messages!

In case you were wondering, this doesn’t work if the signed in user doesn’t have the User Administrator (or higher permissions) assigned to them. Just because a delegated permission like User.Write.All has been configured and consented on an Entra application, it doesn’t mean that any user which is allowed to sign into Graph PowerShell will be able to perform write actions on users.

Because I didn’t set Assignment required? to Yes, any user (including non-admin users) in the customer tenant can now sign into Graph PowerShell but they can’t use all the consented scopes/permissions.

Error message when the signed in user doesn’t have admin permissions

You do not own the App registration

In this example, I’m using the Graph PowerShell (Multi-Tenant) from the service tenant. Note: I’ve re-created this app in the service tenant and named it V4 so Ids in screenshots are now different.

Here are the configured permissions of the service tenant’s app registration and the customer tenant’s enterprise app in comparison. I’m not sure why email hasn’t been added to enterprise app. It might be because it’s already part of one of the other permissions.

App registration permissions in service tenant Enterprise app permissions in customer tenant

Interestingly enough, email appears in the Graph context.

Output of Graph context

Because the app registration in the service tenant has configured permissions, they’re automatically requested during the consent process when the app is added as an enterprise app to the customer tenant.

Let’s start playing around by adding a new delegated permission to the enterprise app in the customer tenant. For this, I’m signing into Graph again by specifying the customer tenant id and the app id of the multi-tenant app that is registered in the service tenant and I’m adding -Scopes "User.Read.All" to Connect-MgGraph. Because this is a new permission, I have to grant consent for it.

As expected, the User.Read.All permission is now listed on the enterprise app in the customer tenant.

Enterprise app permissions

This permission has not been added to Other permissions granted in the app registration of the service tenant like it was the case when both the app registration and the enterprise app were available in the same tenant.

Permissions on app registration in service tenant remain unchanged

This actually makes a lot of sense. Imagine how many permissions would be here if this was the Microsoft Graph Command Line Tools in Microsoft’s service tenant.

Quick Recap

This means that the owner/publisher of the app registration defines what permissions are needed for their app by adding the required permissions as configured permissions. Whatever permissions are configured on the app registration will be the permissions for which the enterprise app will request consent for. Basically, the configured permissions are the minimal permissions required but if you want, you can still add more permissions to your enterprise app because that is specific to your tenant.

Another interesting discovery is that the service tenant doesn’t actually need to have admin consent granted for the permissions on the app registration or on the enterprise app. When the enterprise app is added to the customer tenant, the consent is granted for this tenant only.

Admin consent in the service tenant would only be required if the publisher of the app needed to access information in their own service tenant through their own app.

When I was researching this topic, I briefly panicked and thought that all permissions which are added to the enterprise app/service principal would automatically allow the owner of the app to use these permissions. That would be especially problematic for application permissions. But as I’ve just proven, that’s not the case. The owner of the app can only use what they’ve added under configured permissions. They won’t even see what other delegated permissions you’ve added to your own enterprise app.

Delegated Permissions

With delegated permissions, a signed-in user is required. Now what does that mean exactly? When we’re talking about using Microsoft Graph PowerShell, this is pretty clear. When you run Connect-MgGraph you’re prompted to sign using your username, password and hopefully MFA.

After signing in, the PowerShell session will have an access token which includes information about your user account and the app id that you used to sign in.

This is great for managing Entra ID users and Microsoft 365 services with PowerShell on the fly, like changing the usage location of a user. What delegated permissions are not great for is trying to use them in PowerShell scripts which should run autonomously. If a script is running on some server or in an Azure automation account, there’s no way that you’ll securely get a token for another user. In that case, you’ll want to use application permissions.

Let’s examine another example of delegated permissions using Zoom as a real app example again. The difference between Zoom and a PowerShell script is that you’re signed into Zoom using Entra SSO, so Zoom knows your Entra identity, and it also knows that the signed in user is allowed to read/write the calendar. Unlike a PowerShell script, the Zoom app is something that is continuously running on a user’s machine, and there’s a server piece to it.

When you’re launching the app, you’re authenticating yourself to Zoom and that’s when Zoom acquires the token which allows it to read/write your calendar. Therefore, Zoom can’t access your calendar when the app is not running or when you’re not signed in.

Microsoft Authentication Library (MSAL)

Then there’s the MSAL which is available as a PowerShell module (MSAL.PS). In theory, it could be used in a script but if you’re not a developer (like I’m not) then this will be a whole new rabbit hole to go down. Anyway, even if you were using the MSAL authentication library in a PowerShell script, it would still require the user’s credentials which must be passed in an interactive log in flow in order to acquire a token which could then be used inside the script.

In other words, delegated permissions which typically end in *Read|Write.All are most commonly used by IT admins when they sign into Microsoft Graph PowerShell interactively by providing their admin credentials. Delegated permissions which do not end in *.All usually allow an app to only read/write information of the signed in user. They’re commonly used by apps like Zoom to access relevant data like a user’s calendar.

Application Permissions

Application permissions are used if an app or a script needs access to Entra ID resources without a signed in user. Let’s just say you have a script which runs daily and checks if all the usage location is matching the country property for all Entra ID users. If that script were to use delegated permissions, somebody would need to manually run it every day because the script would prompt for admin credentials in a browser pop-up every time. Such a script will need to utilize application permissions to run in a truly automated way.

To be able to use application permissions, you need a client secret or a certificate and these can only be created on the app registration. That means that if a multi-tenant app were to require application permissions, they would need to be part of the app registration’s configured permissions and you would be prompted to grant consent when you’re adding the enterprise app.

If you own the app registration yourself, you can add new application permissions to the app registration yourself, but you can’t add them directly to the enterprise app, like you can with delegated permissions.

Application Permissions / App Only Authentication

Accessing Graph as application from the Service Tenant

I’m still using Graph PowerShell (Multi-Tenant) V4 as an example. This time, I’m going to add a new application permission to the app registration in the service tenant. For this example, I’m going to add CallRecords.Read.All.

Add application permissions

CallRecords.Read.All is now added as application permission in configured permissions. Note that admin consent hasn’t been granted for the service tenant.

Configured permissions of app registration in service tenant

Because this is an application permission, I can’t simply run Connect-MgGraph and add -Scopes "CallRecords.Read.All. This permission doesn’t even exist as a delegated permission.

Additionally, adding -Scopes is not supported when -ClientSecretCredential is also specified.

Invalid parameter combination error

To add the application permission, I need to get a hold of the admin consent link. Normally, when you add an enterprise app, you don’t need to manually copy and paste a link. This process is usually neatly integrated into the UI of apps that request permission to access your data through Microsoft Graph.

As an example, this is the web page that lets me connect Zoom to my Microsoft 365 calendar. As you can see, there is a nice little Authorize button directly embedded in the Zoom admin portal.

Zoom authorization UI/UX example

When I click Authorize the admin consent dialog is opened in the browser.

Zoom admin consent example

Granting the consent will add the enterprise app. While I’m at it, let’s check out the permissions which were added for Zoom.

Zoom enterprise app permissions

Since these are all delegated permissions, it means that the Zoom app can only access my calendar and contacts when I’m signed into the Zoom app. But the consent flow is the same for both application and delegated permissions.

With the above example, I just wanted to show you what adding an enterprise app usually looks like. I’m not sure if there’s a better way to obtain the consent link to implement it in your own app but for now, what I’m showing you will have to do.

From the enterprise app in the service tenant, I can click Grant admin consent which will open a new browser window. This only works from the enterprise app. If you clicked grant admin consent on the app registration, the grant consent button will open on the same page, and you won’t be able to copy the URL.

Grant admin consent button New browser window with admin consent URL

The new browser window will allow me to copy the URL which will look something like this:

1
https://login.microsoftonline.com/536f948a-babb-4048-836d-717833aa0da5/adminConsent?client_id=c199b3df-a49b-4739-b314-c2ee50e6c0bc&redirect_uri=https://entra.microsoft.com/TokenAuthorize

The first GUID after login.microsoftonline.com is the tenant id of the service tenant. Now I can either replace it with a specific tenant id or just replace it with common:

1
https://login.microsoftonline.com/common/adminConsent?client_id=c199b3df-a49b-4739-b314-c2ee50e6c0bc&redirect_uri=https://entra.microsoft.com/TokenAuthorize

When I open this link and sign in with the global admin of the customer tenant, I can see the name of the app and that it’s requesting the Read all call records permission.

Admin consent request for Read all call records

Unfortunately, application permissions are not labeled explicitly as such which makes it hard to understand what permissions are really requested unless the vendor of the enterprise app includes this info in their documentation. An easy way to figure it out is to search for the permission title or the description in the permission reference.

Back in Entra Admin Center, I can now see that the CallRecords.Read.All permission has been added to my enterprise app.

Enterprise app permissions before granting consent Enterprise app permissions after granting permissions

Just to emphasize on this again, I did not grant admin consent to the configured permissions on the app registration in the service tenant. Remember that consent is always tenant specific.

App registration permissions in service tenant

Create a Secret

An application can access Graph without a signed in user either through a certificate or a client secret. I’m only going to focus on client secrets today.

On the app registration in the service tenant, I’m creating a new client secret.

Add a client secret

Important: the secret is only shown once. As soon as you navigate away from this page, you won’t be able to access it again. When you do this, you’ll see your client secret. It’s only showing a bunch of asterisks for me because I’m using the Cloud Cloak extension for Microsoft Edge.

Added client secret

Using the code below, I (or rather the service tenant) can now sign into the customer tenant using the enterprise app/service principal of the customer tenant and the client secret from the service tenant.

It’s important to understand that I now gave another tenant permission to read all call records in my (customer) tenant without a signed in user of my (customer) tenant.

1
2
3
4
5
6
$tenantId = "4bffbf87-53a0-4fce-b58b-4179cb3a3b7d"
$appId = "c199b3df-a49b-4739-b314-c2ee50e6c0bc"
$appSecret = Read-Host -AsSecureString
****************************************
$clientSecretCredential = New-Object System.Management.Automation.PSCredential ($appId, $appSecret)
Connect-MgGraph -ClientSecretCredential $clientSecretCredential -TenantId $tenantId -NoWelcome

Connecting to Graph PowerShell with app only authentication

Let’s check the Graph context.

Output of Mg-Context

The only scope that’s currently available is CallRecords.Read.All because that’s the only application permission. All the other ones are delegated permissions so they’re not available in this session. AuthType is now AppOnly and we’re still using the Graph PowerShell (Multi-Tenant) V4 app with the client secret from the service tenant.

Finally, let’s see if I can use the app to retrieve a call record from the customer tenant with app only authentication as the service tenant.

Getting a call record with app only permission as the service tenant

Yep, it’s working. It took quite a while for the sign-in logs to appear, but I can now see a logged sign in for the service principal in the customer tenant. In the details, I can see the name of the application and the service principal. I can also see the Application ID which is the app id of the app registration in the service tenant and of course, also the app id of the enterprise app/service principal in the customer tenant. The Client credential type is now Client secret. And finally, the Service principal ID is the Object Id of the enterprise app/service principal in the customer tenant.

Service principal sign in logs in customer tenant Sign in details

Out of curiosity, I checked the sign in logs in the service tenant as well. I want to point out that the enterprise app in the service tenant is still untouched and does not have any consented permissions. Nevertheless, the sign-in logs of the service tenant still log the sign-in activity, even when the sign in happened in the customer tenant. It also lists the Service principal ID of the customer tenant even though that object id doesn’t exist in the service tenant. There is no reference of the customer tenant id, though.

Enterprise app permissions in service tenant Sign-in log details from service tenant

When application permissions are used in multi-tenant apps, only the owner/publisher of the app registration will be able to use the application permissions, because you don’t have access to the secret and you can’t create one for yourself either because you don’t have access to the app registration.

Accessing Graph as App from your Own Tenant

If you want to use Graph PowerShell with application permission (without a signed in user) in your own tenant, the process is exactly the same as I’ve just shown you for a multi-tenant scenario.

You just need to create your own app registration, assign the required permissions and create a client secret or a certificate for the app. In that case, you’ll obviously have to grant admin consent because you want to access Graph as an app in your own tenant.

Accessing Graph as App using your own App Registration from a 3rd Party App

What I described in Accessing Graph as application from the Service Tenant would allow the service tenant to read call records of all tenants that have consented to their app. Another scenario you might encounter is that a vendor of a software/service asks you to create your own app registration but share/configure your secret in their service.

I’ll use Bitwarden, which is my favorite password manager, as an example for this. Bitwarden allows an organization to sync their Entra ID users to Bitwarden so that you can then specify which of your Entra users will be able to use Bitwarden from their admin portal.

This is a perfect example of why an app would need Users.Read.All and Groups.Read.All application permissions.

Bitwarden doesn’t actually provide their own enterprise app which can be added to your tenant. Instead, their documentation states that you as the customer have to create your own app registration and which delegated and application permissions you need to add to it.

Required delegated and app permissions for Bitwarden Directory Connector

Further down the line, their documentation explains that you need to create a client secret. Once you have everything, namely the tenant id, the app id and the client secret, you need to add them to their Directory Connector app.

Bitwarden documentation on how to connect Directory Connector to your Entra app

I don’t know all the details about this Bitwarden Directory Connector but to put it simply, adding your tenant id, app id and client secret to it, will allow the Directory Connector to read all your Entra users and sync them to the Bitwarden admin portal.

By doing it like this, Bitwarden delegates the management of the app registration to the customer and they’re also making sure that the data in your tenant can only be accessed by your app secret/your own instance of Directory Connector.

Deleting Apps

Lastly, after all this testing, it’s time to clean up my lab. Let’s see what happens when enterprise apps and app registrations are deleted.

Deleting an Enterprise App

You Do Not Own the App Registration

Since enterprise apps are always tenant specific, deleting an enterprise app will only delete it from your tenant. This has no impact on other tenants. Enterprise applications can be deleted from the Properties menu.

Properties of multi-tenant enterprise app in customer tenant

If you delete an enterprise app by accident, you can easily add it again by granting consent again. Depending on the app and the required permissions, you can do this by signing into Graph PowerShell or by using the admin consent link again. Because enterprise apps can’t be restored, adding one again will generate a new object id for the enterprise app/service principal.

Your Own Enterprise Applications

If you delete an enterprise application for which you own the app registration and both are in the same tenant, deleting the enterprise app won’t delete the app registration as well. However, deleting the enterprise app will remove previously consented permissions on the app registration too.

Here, I’m deleting the enterprise app called Graph PowerShell Demo (Created in Portal). Deleting an enterprise app will result in revoking all admin consents, including configured permissions.

App registration permissions before the enterprise app was deleted App registration permissions after the enterprise app was deleted

If you delete the enterprise app by accident, you can create a new one by granting admin consent on the app registration again. Keep in mind that the new enterprise app will have a different Object ID. The Application ID stays the same, as it’s the one of the app registration anyway.

Deleting an App Registration

When you’re deleting app registrations you need to be much more careful.

Your Own Single-Tenant App Registrations

If you delete an app registration for which an enterprise app exists in the same tenant as well, both objects will be deleted.

App registrations can be deleted from the Overview page.

Delete app registration

A Multi-Tenant App registration which you own

If you’re the publisher/owner of a multi-tenant app registration and you delete the app registration from your service tenant, both the app registration and the enterprise app/service principal will be deleted from the service tenant. The enterprise app won’t be deleted from customer tenants but customers will no longer be able to sing in and use the app!

Let me share a great real life example with you. Until September 9th 2024, the PnP.PowerShell team has provided a multi-tenant app which could be used to sign into the PnP Management Shell. They announced that the app will be deleted on that day. As a result, any tenant that had added this app as an enterprise app to their tenant can no longer use it. Instead, admins need to create their own app to access the PnP Management Shell.

If the app registration is deleted in its home tenant by the app publisher/owner, it’s best to remove the enterprise app from your own tenant as well.

Let’s get back to my lab. I’ve now deleted the app registration for Graph PowerShell (Multi-Tenant) V4 from the service tenant.

As expected, after deleting the app registration from the service tenant, it’s not possible to sign into the enterprise app in the customer tenant anymore, even though the enterprise app still exists and the permissions of the enterprise app remain unchanged.

Error message when app registration was deleted in service (home) tenant Permissions of enterprise app in customer tenant

Restoring App Registrations

Unlike enterprise apps/service principals, app registrations can be restored for up to 30 days. If an app registration was deleted by accident, you can restore it from Deleted applications in the App registrations menu.

Restoring deleted app registration in service tenant

This will restore the enterprise app in the home tenant as well. In my case, both the consented permissions for the enterprise app and the app registration were restored as well. I did restore it right after deleting it though. The results might be different, if more time passes between deletion and restore.

Let’s get to the million dollar question. Is there any action to be taken in the customer tenant after an app registration was deleted and restored from the service tenant?

Successful sign in after the app registration was restored in the service tenant

In my case, signing in to Graph PowerShell worked again just a few seconds after the app registration was restored in the service tenant. Again, this might differ if the time difference between deletion and restore is bigger.

Other Types of Service Principals

So far, we’ve learned that every enterprise application is also a service principal. But is every service principal also an enterprise application? Not quite. If you navigate to the Enterprise applications page in Entra Admin Center, you’ll notice that the filter is automatically set to Application type == Enterprise Application.

Enterprise applications view

That means that the portal will only show enterprise apps which have explicitly been added by an admin (or a user if not blocked) to your tenant.

To block users from adding enterprise apps to your tenant, go to Enterprise applications in Entra Admin Center and then click on Consent and permissions on the left navigation pane.

Consent and permissions Do not allow user consent

However, there are also different types of service principals which are also part of the enterprise applications menu, but not included with the default filter.

Service principal types

Microsoft Applications

Microsoft applications are apps owned by Microsoft and they mostly include apps which allow Entra ID users to access various systems and services within Azure and Microsoft 365. My lab tenant currently lists 585 Microsoft apps. That is way too much to go into detail for all of them but let’s look at the example of the Microsoft Graph. This is the actual Graph API and not the Microsoft Graph Command Line Tools enterprise app.

There’s also an Application and an Object ID for Microsoft Graph. Unlike Enterprise apps, Microsoft apps can’t be deleted and various properties such as Assignment required? are not available. Searching for the app id will list it as enterprise application/service principal as well.

Microsoft Graph (Microsoft application) Entra Admin Center search result

A list of the most commonly used app ids for Microsoft applications can be found here.

The actual Graph application doesn’t have or needs any permissions consented.

Microsoft Graph (Microsoft application) permissions

If I go back and look at the sign-in logs of when I signed into Graph PowerShell using my Graph PowerShell Demo (Created in Portal) app, I can see that the Resource ID lists the app id of the Microsoft Graph Microsoft app (00000003-0000-0000-c000-000000000000).

Sign in logs of Graph PowerShell

I think it’s worth pointing out that the service principal is called GraphAggregatorService but the app itself is called Microsoft Graph.

Managed Identities

Managed identities are service principals which are tied to specific Azure resources like an automation account or a function app etc.

Managed identity service principals

This is an Azure resource of an automation account, for which I’ve configured a system assigned managed identity. If you look closely, you can see that the Object (principal) ID is the same as the Object ID of the service principal in the screenshot above.

Managed identity on Azure resource

Once the system assigned managed identity is enabled, this resource will be registered with Microsoft Entra ID. After being registered, you can control its access to other services like storage accounts.

― Azure Portal

Managed identities do not have an app registration exposed to your tenant but when you enable one for an Azure resource, an app will be registered somewhere in Entra ID (where only Microsoft can see it) and a service principal will be created in your tenant.

Entra Admin Center search results for managed identity object id

Managed identities are primarily used to grant access to Azure resources, therefore the permissions of the enterprise app are usually empty.

Permissions of managed identity service principal

However, it is possible to assign administrative roles to service principals of managed identities or grant them access to Azure resources other than the one for which the managed identity was created for.

Admin role assignment for service principal (managed identity)

A managed identity can only be used by the Azure resource for which it was created for. So, if you create a managed identity for an Azure automation account, only the automation account, or resources within said automation account, for example a runbook will be able to sign in using that managed identity. The managed identity cannot be used in any other way. It’s also not possible to create a client secret or a certificate for a managed identity because as the name suggests, Microsoft is doing everything in the background for you.

To connect to Azure using a managed identity in an Azure runbook, all you need is this code:

1
2
# Connect to Azure environment
Connect-AzAccount -Identity -TenantId $tenantId

Service principals of managed identities cannot be deleted from enterprise applications.

Managed identity service principal properties

Instead, the managed identity must be disabled on the page of the Azure resource for which it was created.

Disable managed identity from Azure resource configuration

Summary

This is without a doubt the longest blog post I’ve ever written. But sometimes, when I’m writing about complex topics there is just no other way to do this. I’m aware that I’ve repeated myself a couple of times in this blog post, but I wanted to make sure that it’s clear at all times if I’m speaking about an app registration or an enterprise app and in which tenant the afore mentioned object lives.

I also want to clarify that I’ve never developed or worked on an enterprise grade application or anything like that. That’s also why this blog post doesn’t go into the details like token configuration, exposing APIs etc.

As a Sys Admin, you’re going to have to deal with Entra applications sooner or later. Whether you like it or not. It sure does complicate a lot of things that were easier a couple of years ago, like using the AzureAD PowerShell module and not having to deal with Graph permissions for example. But I believe that it’s a necessity for every IT Pro to learn how things work in the new world. It’s important to understand what an app registration and what an enterprise app is and what each of them does.

I actually wrote about a third of this blog twice. The first time I started it was a hot mess and there was no clear common thread to follow. In my first attempt, I tried to sort everything into sections, like creating an app registration and then I had subsections for each possibility like single- and multi-tenant but it just didn’t make much sense to talk about registering multi-tenant apps, when I hadn’t even explained what a multi-tenant app is or in which scenarios they’re used.

Then I started from scratch again and I tried really hard two write a story that unfolds naturally. I started with things you might already know and introduced new stuff that builds on previously mentioned details in each topic.

Let us reminisce one last time what Entra applications are and what the key differences between app registrations and enterprise apps are.

An Entra application in general is referring to what’s used when certain resources like the Graph API are accessed in Entra ID. Access to resources can either use delegated permissions, where a signed in user is required or they can use application permissions, where either a client secret or a certificate instead of a signed in user is required. An application can have any combination of delegated and application permissions.

An Entra application is not like a traditional application. When we hear the word application or app, most people will think about an app that can be installed on a device or accessed through a web browser. The purpose of an Entra application is to allow actual apps, like for example the Zoom client to access resources like your calendar in Entra ID/Graph. Any Entra application must be registered in an Entra ID tenant before it can be used in applications or scripts that are built by developers.

An app registration is essentially the same thing as an application. The process of creating a new application is called registering an app and that’s why the Entra Admin Center typically calls them app registrations. In PowerShell or Entra ID logs, app registrations are always called applications.

In theory, an app registration can exist without an enterprise app, but an enterprise app can’t exist without an app registration. The registered application for an enterprise app can either be in the same tenant or it can be homed in a different tenant.

When you’re building an internal application, the app registration is usually homed in your own tenant. When you’re purchasing, using or building a SaaS app, the app registration usually lives in a service tenant.

When an app is registered, a globally unique (across all Entra ID tenants) application id is assigned by Entra ID, and an app can be registered as a single- or a multi-tenant app. Single-tenant apps can only be used by your organization. Multi-tenant apps can be added to and used by any tenant, if admin consent for the app is granted.

Enterprise apps are the same thing as service principals but not all service principal types are also called enterprise apps. Microsoft applications and managed identities are the exception to this. The Entra Admin Center refers to service principals as enterprise applications in most UI elements but logs in Entra ID or PowerShell Cmdlets and object properties typically refer to them as service principals.

Service principals allow you or a publisher of a multi-tenant app to access resources in your tenant. The permission model is very granular and almost any action requires an explicitly granted admin consent before an app is allowed to perform any actions. This also applies when using delegated permissions and means that you won’t be able to perform an action against the Microsoft Graph API before admin consent has been granted, even if your account has the required admin roles assigned and you’re able to perform the same action in the portal.

To use app only authentication a client secret or a certificate is needed, and they must be configured on the app registration, even though the service principal is used for the actual sign in process.

In conclusion, an Entra application is a combination of both an app registration and an enterprise app. You can’t have an enterprise app without a registered app, and you can’t use an application to sign into a resource, such as Microsoft Graph without also having an enterprise app/service principal for it.

I hope that this explanation makes sense to you. I certainly learned a lot in the days I dedicated my time to writing this blog post. If you too understand the difference between app registrations and enterprise apps now, feel free to buy me a coffee. 😊

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