Following on from part 1, we are going to be delving further into the Entra ID specifics and quirks of configuring three key components:

  • Application Registrations
  • Enterprise Applications
  • Service Principals

We will be clarifying what each of these is, how they relate to each other, and trying to clear up some of the general confusion around how they are presented and configured within the Entra ID portal.

If you haven’t already done so, I recommend reviewing part 1 to familiarise yourself with some of the concepts we will discuss today, namely SAML, OAuth 2.0, and OIDC.


Overview

Anyone who has worked with Entra ID applications can attest to it being a bit confusing. Do any of these sound familiar?

  • “I just want to create some credentials for a script - why do I need to register an application?”
  • “I need to integrate an application with SAML - is that an enterprise application or application registration?”
  • “Why do I see the same application under both enterprise applications and application registrations?”
  • “I’ve no idea where this enterprise application came from - we shouldn’t be using it. How did it get there?”
  • “How can I check what my users have actually been consenting to?”

You’re not alone!

Let’s kick things off by looking at defining some key terms.


Service Principals

Service principals in Entra ID can be thought of as identity for an application, or other non-human workload (such as automation scripts). They are essentially usernames and (optionally but not always) passwords created for applications/machines/automation scripts (etc). It provides them with an identity in your tenant that can be assigned permissions.

The slightly confusing part within Entra ID is that these are intrinsically coupled with the term “application”, which when we think about things like automated scripts and Infrastructure as Code, is not a term that naturally springs to mind. In Entra ID, applications and service principals are intrinsically coupled. You cannot create a standalone service principal without an associated application registration.

Let’s say you are using Terraform to deploy resource via Infrastructure as Code. It needs some credentials to authenticate, so you may run a command such as the following to create a service principal…

az ad sp create-for-rbac --name "terraform-project-x-prd"

Although the command specifically referenced “sp” (for service principal), that isn’t all that was created. We can see an application registration as well…

application Registration via CLI

When you create an application registration, you are registering an application with the Microsoft identity platform so that it can be used as part of Oauth2.0 or OIDC flows. Even if you plan on using no other “application” functionality, and just want it as an unattended service account, you still need to register it so you can authenticate using OIDC credentials.

application Registration via GUI


Application Registrations

Turning to the Microsoft docs we can see they have the following to say about an application registration…

“Registering your application establishes a trust relationship between your application and the Microsoft identity platform. The trust is unidirectional: your application trusts the Microsoft identity platform, and not the other way around. Once created, the application object cannot be moved between different tenants.”

What else is going on with these application registrations…

  • Registering with the Microsoft Identity Platform - As mentioned above, when we create an application registration it gets assigned a globally unique client ID (remember “client” meaning the application in OAuth2.0/OIDC terminology). This allows us to integrate with the Entra ID platform for authenticating users/consenting to permissions, or in the case of a simple “automation account”, create credentials and authenticate using OIDC.
  • It creates a service principal - As we saw in the previous section, service principals and applications are intertwined in Entra ID. When we create an application registration, we automatically create a service principal in OUR tenant (more on that in a bit).
  • Setting any credentials it may need - For several of the OAuth2.0 flow types, our application will need a secret to prove it’s identity to the Microsoft identity platform and retrieve the access tokens required to go and consume user data. If the “application” is just being used as an “automation account”, the client ID and secret will essentially act as a username and password.
    • For example, if plumbing this into Terraform, you may pass the environment variables ARM_CLIENT_ID and ARM_CLIENT_SECRET to Terraform, which in turn will be used to authenticate against Entra ID with OIDC.
  • Specifying what consent scopes the application requires - You may need to define what permissions your application will require consent for. If our application wants to access a user’s mailbox, then it may need Mail.Read permission from the Microsoft Graph APIs.
  • Defining what APIs scopes this application exposes for others - Perhaps our application is also going to expose some APIs. We document these under the application registration. Much like Microsoft Graph exposes ‘Mail.Read’, maybe our application will expose ‘Mail.Summarised.Read’ if we are creating some sort of email summary application.
  • Defining the application roles - Roles define what users of your application can do and are passed back to your application during the login process. These can later be used when assigning users or groups to the application. As a simple example, maybe you will have a standard user role and an administrator.

Single vs Multi-Tenant Applications

When registering applications, we have a few options on the supported account types. Which you select will depend on who your target audience is.

  • Accounts in this organizational directory only (Single-tenant).
  • Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multi-tenant).
  • Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multi-tenant) and personal Microsoft accounts (e.g. Skype, Xbox).
  • Personal Microsoft accounts only.

If you’re just registering an internal application (or an automation account) that will only ever be used by your company, you’re going to want to select the first single-tenant option. If however, you are creating an application that you intend other organisations/individuals to consume, you’ll want to select one of the others.

Earlier we touched on the fact that an application registration also creates a service principal in our tenant. This is always the case, however what happens if we create a multi-tenant application?

Each tenant that onboards our application will also create a service principal in their tenant. So, whilst the definition of the application (and any secrets it may use) are housed in its “home tenant”, a unique service principal will be created in every tenant where it is used, providing a local identity for which permissions can be assigned. This is illustrated below:

Multi-Tenancy

Hopefully things are starting to make some more sense. To recap briefly on application registrations:

  • They register the application with Microsoft so it can be used with OAuth2.0 and OIDC.
  • They create a local service principal in our tenant.
  • They allow us to define the OAuth2.0 scopes the application wants to use.
    • They also allow us to consent to them for all users if we are a global administrator.
  • They allow us to define other attributes such as application roles, owners, branding, terms of service etc.

Delegated vs Application Permissions

The whole idea for this article originally stemmed from my colleague’s confusion around this point. When we define the OAuth2.0 scopes our application needs, we have two options - delegated and application permissions.

Delegated permissions are permissions that an application has when it is acting on behalf of a user. This means that the application can only access resources that the user has permissions to. For example, if only Joe Bloggs consents to allowing Mail.Read, the application can only access Joe’s mailbox and no one else’s.

Application permissions are permissions that are granted to the application identity itself, allowing it to act independently of any user. This means the application can access resources without a user context. If we defined the Mail.Read permissions with an application scope, then it could read the mailboxes of ALL users.

Users may or may not be able to consent based on your tenant’s security settings, and broader application permissions generally require admin consent anyway.

A couple of key takeaways:

  • If you are defining an application registration purely for an “automation account” of some sort, you’ll most likely want to set this to application permissions (unless directed otherwise).
  • If you are creating an application that may be consumed by other tenants, you’ll probably want to think about delegated permissions - other organisation admins may not be happy approving full access.

Enterprise Applications

Knowing now that an application registration is just the ‘definition’ of an application, and that a service principal is created in each tenant to represent that application, we can now come onto the final piece of the puzzle - enterprise applications.

For all intents and purposes, enterprise applications can be thought of as a view of the service principals created in your tenant, along with any settings related to the application sign-on etc.

If you go and have a look at your organisation’s enterprise applications, there is a good chance you’ll find yourself saying…

“WTF are all these random applications?! We shouldn’t be using half of these!”

This may suggest it is time to review your security settings, but we aren’t getting into that today.

Applications will appear under your enterprise applications view for a number of reasons:

  1. Application registrations you’ve created - Remember, even if that application registration was only for a “service account” it will still have a service principal created automatically and will still be shown under your enterprise applications.
  2. Users or admins have consented to third-party apps - If your users or administrators have consented to other applications gaining access to your resources, you’ll see these under enterprise applications. You won’t however see an application registration for these, as you didn’t create the application. Referring back to the earlier diagram, you’d essentially be “tenant two” in this scenario. For each of these applications, you’ll be able to see who has consented to and what they consented to.
  3. Apps added manually or via the enterprise application gallery - You may have added third-party applications via the enterprise application gallery or manually so you can set them up for (most likely) SAML SSO. Confusingly, when you do this, it also creates an application registration - is it any wonder people get confused!? More on this in a bit.

Some of the settings you will find under enterprise applications:

  • Application details - Details on the application - URLs, IDs, branding etc.
  • Assignment to users and/or groups - Under the enterprise application you specify which users are allowed to sign into this application with Single Sign-On (SSO) and what roles they will be assigned.
  • Single Sign-On (SSO) Settings - This is where you’d setup the relevant SSO settings to allow people to login with the Entra ID account using either SAML, password-based storage or a “linked” application (the latter two not being something I’ve seen people use).
    • CONFUSION WARNING! - If the application is one that you have created via an application registration, you cannot configure this section. You can only use OIDC.
  • Automatic provisioning - Where supported, you can setup any automatic provisioning via System for Cross-domain Identity Management (SCIM). SCIM prevents you needing to create users in the target application manually.
  • Granted permissions - The enterprise application keeps track of which users/administrators have consented to permissions, and what scopes were granted.

I just want to re-emphasise one of the points above regarding SSO… if you create an application registration first, you can only use OIDC for SSO. You will see a message that looks as follows if you were hoping to configure SAML:

OIDC Message in Enterprise Application

I’d like to say that is where the confusion ends, but unfortunately it doesn’t 😄.


Adding a SAML Application

Let’s say we want to configure SAML SSO for an application from the enterprise application gallery. We go there, search for what we want (in this instance, I’ll just pick Zoom).

We add the gallery app…

Zoom Gallery App

And as we expect, the application is now available under enterprise applications, and we can configure the Single Sign-On settings…

Zoom SSO Settings

But wait… What’s this… An application registration?!

Zoom application Registration

The process can be confusing:

  • If you start by creating an application registration, you can’t configure SAML SSO.
  • If you start by adding an enterprise application, you can configure SAML SSO, but it also automatically creates an application registration.

This behaviour can understandably confuse many users. Don’t worry though, I’ve summarised what you need to remember in The TL;DR section below.

Viewing Consents

Before we look to wrap things up, I just wanted to revisit what I said earlier about viewing granted consents. Assuming your users have permissions to consent to various OAuth2.0 scopes (which depends on your Entra ID settings), then you can view these consents by navigating to the enterprise application, then heading to the permissions blade.

Admin Consent

User Consent

You could of course view these with a bit of CLI magic too. After a bit of trial and error with ChatGPT, I’ve knocked up a quick PowerShell script with the az cli, that will export a list of enterprise applications and their consents to an Excel spreadsheet. Note, this uses the -Parallel flag with ForEach-Object, so you’ll need PowerShell 7.

It’s very rough around the edges - I may improve it if I find time, for now - it’ll do as an example.

# Install ImportExcel if not already installed
if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
    Install-Module -Name ImportExcel -Scope CurrentUser -Force
}

# Create an array to hold results
$results = @()

$servicePrincipals = az ad sp list --all --query "[].{ObjectId:id, AppDisplayName:displayName}" --output json | ConvertFrom-Json

# Process each service principal in parallel
$jobs = $servicePrincipals | ForEach-Object -Parallel {
    $output = @{
        "application Object ID" = $_.ObjectId
        "application Name" = $_.AppDisplayName
        "Consents" = ""
    }

    $result = az ad application permission list-grants --id $_.ObjectId --output json

    if ($result -eq "[]") {
        $output["Consents"] = "No consents authorised"
    } else {
        $permissions = $result | ConvertFrom-Json
        $consentList = @()
        foreach ($permission in $permissions) {
            $consentEntry = "ConsentType: $($permission.consentType), Scopes: $($permission.scope)"
            if ($permission.PSObject.Properties.Name -contains 'principalId') {
                $consentEntry += ", PrincipalId: $($permission.principalId)"
            }
            $consentList += $consentEntry
        }
        $output["Consents"] = [string]::Join("`r`n", $consentList)  # Use `r`n for Excel line breaks
    }

    $output
} -ThrottleLimit 20 -AsJob

Write-Host "Waiting for parallel jobs to finish (this may take a minute or two)..."
$results = $jobs | ForEach-Object {
    $_ | Wait-Job | Receive-Job
    Remove-Job -Job $_
}

# Export results to Excel
Write-Host "Exporting results to Excel..."
$formattedResults = $results | ForEach-Object {
    [PSCustomObject]@{
        'application Object ID' = $_.'application Object ID'
        'Consents'      = $_.'Consents'
        'application Name'      = $_.'application Name'
    }
}
$formattedResults | Export-Excel -Path "entra_id_consents.xlsx" -AutoSize -Title "Application Consents"

The TL;DR

Putting aside the confusing way certain things work in Entra ID, I’ve tried to summarise what you need to know below.

“I want an account for a workload (such as an automation script)”

  • Create an application registration for your tenant only. Add secrets as necessary and assign permissions as you need. You don’t need to worry about URLs etc.
  • Make sure you are assigning application permissions (not delegated permissions) if configuring as part of the application registration.
  • Depending what permissions you need, they may not need to be assigned via OAuth2.0 at all - you may just assign Entra ID roles or Azure permissions to the service principal identity as you normally would a regular user.

“I’m developing an internal application that needs to use Microsoft to authenticate users and/or retrieve permissions via OAuth2.0”

  • Create an application registration, paying more attention to details such as URLs and permissions etc.
  • Once setup, users can be assigned access to the application in the enterprise application.

“I need to create a multi-tenant application”

  • As above, but make sure you select one of the multi-tenant options, otherwise users from other tenants won’t be able to login.
  • You can control assignment to your application in your own tenant, but other tenants will be responsible for their own assignments.

“I need to integrate a third-party application with SAML”

  • Straight to enterprise applications section! Add an enterprise application (manually or via the gallery) then proceed to setting up the relevant SSO settings.

“I need to configure some additional claims for a SAML application I’ve already added to enterprise applications”

  • You’ll need to head to the application registration that was automatically created when you added the enterprise application.

“I want to check what permissions users have consented to for an application”

  • Go to enterprise applications, find the app, and check the “permissions” blade to see granted permissions.
  • Or use the dodgy PowerShell script ChatGPT and I knocked up.

“Where do I see the application registration for a third-party application my users consented to?”

  • You can’t. If this isn’t an application you’ve created, you won’t be able to see the application registration. That is defined in the home tenant of the company who created it. You are just consuming their multi-tenant application.

“I need to revoke access for a specific application”

  • Again, in enterprise applications, find the app, navigate to permissions and revoke as necessary. Alternatively, go in heavy handed and delete the enterprise application altogether.

Additional Learning

One of the best videos I watched on this subject when I was learning it, was the following from John Savill:

His videos are always clear and easy to understand - if you’re not following him and watching his content, I’d strongly recommend it. He is a legend when it comes to all things Azure.


Conclusion

It is a confusing area, but hopefully this has helped clear things up for you a little bit. If nothing else, and you still don’t get it, at least you hopefully know the right screens to head to 😉!

In a future article, we will have a look at how we can apply some controls to the permissions that users are consenting to, and what challenges these can bring.