At time of writing (April 2024), adding and using Enterprise Applications in Admin Units is not Supported by Microsoft yet.
In fact, I am not aware of any official Previews. This Article is purely me playing around, if you use any of this in Production it’s on you.
I have written quite a few Articles at least tangentially realated to least privilege, so it should come as no surprise that I like Administrative Units. As a matter of fact I like them a lot – who doesn’t like taking away permissions that people don’t need – for Security reasons. Well, I don’t think it even crosses many minds, but that’s not the point😤.
In my article decrying the use of Application.ReadWrite.All Application Permissions, I explicitly list Admin Units (AUs) containing Enterprise Apps and their App Registrations as a potential solution – But that is not the only place they would be very helpful – If you are not already treating Cloud App Administrator as a Global Admin you should run a report of your Enterprise Applications and remind yourself: A Cloud App Administrator can use all those juicy Application Level Permissions by creating new app credentials.
It would be great if we could create a group of all the less critical applications for our day-to-day admins and limit the management of all apps to our most trusted folks – without weaving an annoying net of ownership or role assignments…
I am saying we shouldn’t need an IAM connector or custom interface, I see you fellow creators of apps that will be legacy in 2-5 Years 👁️
So, how close are we to getting access to this feature extension?
The Official Point of View
First of all, let’s have a look at the official documentation to see what we should be able to do:
So we can scope Users, Groups and Devices, nothing else. This limitation is reflected in the GUI, where only these categories are listed:
When we try to add a member, the objects available to us are always filtered to the appropriate category. So, since Enterprise Apps are not available in the GUI and not explicitly documented, we can’t add Apps to Admin Units right?
Adding Apps to Admin Units
I don’t believe in GUIs.
As in, I use them and acknowledge their utility. To be sure of something or understand weird behaviour however; I always turn to the command line, config files, or, in this case, the API. This is especially true given Microsoft follows an API-first paradigm, which generally means more robust and up-to-date options are available through the Graph API. Unless the application or feature predates what feels like a 2020 cut-off. But I digress.
So – since we know the UI won’t let us play, let’s see what Graph gives us to draw on:
Prerequisites: A User with Privileged Role Administrator and an already created Admin Unit. The Admin Unit ID can be retrieved from the overview.
# Replace with your Values
$enterpriseAppObjectID = "<Enterprise App Object ID>"
$appRegistrationObjectID = "<App Registration Object ID>"
$adminUnitID = "<Admin Unit Object ID>"
# Add Enterprise App and App Registration to Admin Unit:
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/servicePrincipals/$enterpriseAppObjectID"
}
Invoke-MgGraphRequest POST "https://graph.microsoft.com/v1.0/directory/administrativeUnits/$adminUnitID/members/`$ref" -Body $params
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/applications/$appRegistrationObjectID"
}
Invoke-MgGraphRequest POST "https://graph.microsoft.com/v1.0/directory/administrativeUnits/$adminUnitID/members/`$ref" -Body $params
# Show Result:
$res = Invoke-MgGraphRequest GET "https://graph.microsoft.com/v1.0/directory/administrativeUnits/$adminUnitID/members/"
$res.value.'@odata.type'
Et voilà: we’ve successfully bent the rules. Typically, there are safeguards to ensure we can only add authorized elements, maybe this feature is nearly ready for official preview, allowing us some leeway?
Applications are still not visible in GUI – there`s no "All Members" Button 😉
Application Roles scoped to Admin Units
Adding the Application Objects to AUs isn’t particularly useful on its own. Without the ability to easily view applications’ memberships within AUs, it doesn’t help categorize applications (we have custom security attributes for that). The real value of AUs lies in enabling more targeted permissions, enabling the principle of Least Privilege by allowing targeted Cloud App Administrator assignments.
First things first, let’s test if we can add a Cloud Admin role through the GUI:
Admin Unit Role Managmement Dialogue | Add Role Assignment Dialogue |
---|---|
Well, it turns out that neither adding the role through Privileged Identity Management (PIM) nor the AU-specific role dialogue provides the options we need. So, we’re turning back to our reliable friend the Graph API:
# You could also use an Enterprise App ID here
$userID = "<ID of my not-yet-privileged User>"
# We have to resolve UPNs, since they are not allowed in Role Assignments
$userID = (Invoke-MgGraphRequest GET "https://graph.microsoft.com/v1.0/users/$userID").id
$params = @{
"@odata.type" = "#microsoft.graph.unifiedRoleAssignment"
roleDefinitionId = "158c047a-c907-4556-b7ef-446551a6b5f7" # Cloud Application Administrator
principalId = "$userID"
directoryScopeId = "/administrativeUnits/$adminUnitID"
}
Invoke-MgGraphRequest POST "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments" -Body $params
Side Note: The PIM GUI is flexible enough to show this role assignment – which simplifies tracking compared to running a script to fetch all ownership assignments.
Now that we have a user with permissions scoped to the Admin Unit, let’s verify everything behaves as expected. I’ll log into both the GUI and PowerShell as BiancaP, the newly assigned Cloud App Administrator, using fresh sessions. Next, we’ll perform common administrative tasks to see where access is denied — or erroneously granted:
Managing App Properties
To reiterate, we are now acting as our AU limited Cloud App Admin BiancaP on App Registrations and Enterprise Applications added to our AU, unless explicitly stated otherwise!
Tests on our AU Apps were surprisingly successfull in the GUI. Hence, it makes more sense to list the current limitations (as of April 2024):
- Adding Owners to Enterprise App and App Registration
- Encountered inconsistency: initially, I was able to add the user himself and then others, but I would intermittently get "permission denied" errors
- This limitation does not apply to direct API calls, where I encountered no issues
- Updating the Manifest
- I found no way to edit the Manifest file as BiancaP
SAML Configuration: Remember, Admin rights on both the App Registration and the Enterprise App are necessary for adjustments (e.g., Redirect URI and Identifier, which are properties of App Registration)
For API verification, I performed quick spot checks. Given that the GUI interfaces with the Graph API, it’s reasonable to expect that the API will behave similarly, if not offer more capabilities where the GUI hits its limits.
# Disabling the Enterprise App ( = Enabled for users to sign-in )
$params = @{
accountEnabled = $false
}
Invoke-MgGraphRequest PATCH "https://graph.microsoft.com/v1.0/servicePrincipals/$enterpriseAppObjectID" -Body $params
# Enable Public Client, Add a Redirect URI ( You can't remove the primary redirect URI)
$params = @{
isFallbackPublicClient = $true
web = @{
redirectUris = @("https://jwt.ms/saml", "https://jwt.ms/demo")
}
}
Invoke-MgGraphRequest PATCH "https://graph.microsoft.com/v1.0/applications/$appRegistrationObjectID" -Body $params
Both run successfully and have the expected Result:
Updated App Registration Properties | Updated Enterprise App Properties |
---|---|
If we attempt to edit properties of an application that is not included in the AU, it is not permitted, as expected:
Message App Registration
Message Enterprise App
Message API calls (that worked earlier 😉)
Managing Owners
As mentioned, to circumvent the weird behaviour in the GUI, I tested adding an owner through the Graph API. This method also bypasses restrictions on editing the manifest and allows us to delete Enterprise Apps and App Registrations. However, while useful for testing, I would not call this appropriate for regular administrative use.
$userID = $GraphConfig.AUUser
$userID = (Invoke-MgGraphRequest GET "https://graph.microsoft.com/v1.0/users/$userID").id
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$userID"
}
Invoke-MgGraphRequest POST "https://graph.microsoft.com/v1.0/applications/$appRegistrationObjectID/owners/`$ref" -Body $params
$params = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$userID"
}
Invoke-MgGraphRequest POST "https://graph.microsoft.com/v1.0/servicePrincipals/$enterpriseAppObjectID/owners/`$ref" -Body $params
Results are again as Expected:
Updated App Registration Owners | Updated Enterprise App Owners |
---|---|
Creating and Deleting Apps
I won’t return to the GUI, since there’s no Application Tab within the AU — definition of insanity, right? 🤪 Additionally, creating apps outside the Admin Unit is predictably disabled:
Unfortunately, we now face more explicit limitations of the API endpoint. We can create Groups, and only Groups, within Administrative Units:
Trying anyways results in the documented error:
#Create New Member:
$params = @{
"@odata.type" = "#Microsoft.Graph.Application"
"displayName" = "New Member"
}
$res = Invoke-MgGraphRequest POST "https://graph.microsoft.com/v1.0/directory/administrativeUnits/$adminUnitID/members/" -Body $params -OutputType PSObject
For those wondering if it was simply a case of mistyping, that would trigger a distinctly different error — which, of course, I tested on purpose. 😇
Moving on, Permissions scoped to the AU do not permit the removal of apps, as demonstrated here:
Attempting to delete via the Graph API similarly results in denial:
Invoke-MgGraphRequest DELETE "https://graph.microsoft.com/v1.0/directory/administrativeUnits/$adminUnitID/members/$appRegistrationObjectID"
If we add ourselves as an owner, we can delete the application in the usual manner:
Invoke-MgGraphRequest DELETE "https://graph.microsoft.com/v1.0/applications(appId='$appID')"
All in all, not the most satisfying result.
How I came here
The main reason I started poking around with these tests? I just couldn’t wrap my head around the idea that there isn’t a streamlined way to enable app creation without slapping on some seriously broad permissions on me and my fellow Entra Admins. This whole issue really boils down to quirks of the "Application Developer" role.
My first headache is tracking who owns what. When an Application Developer creates an app, they’re automatically added as an owner, otherwise they couldn’t manage it. But if you’re aiming to co-manage apps, the first owner has to manually add any other necessary owners – groups are not an option. Either that, or we’d have to rig up some kind of automation, probably using custom security attributes, to smooth things over. It feels like there should be a better way, right?
More importantly, an Application Developer can’t create SAML Applications, since that requires "instantiating" an Application Template , a task that falls outside the permissions of the role. Specifically, it requires microsoft.directory/applicationTemplates/instantiate
, which is not included in Application Developer. Even if this permission is granted through a custom role, it doesn’t automatically make the creator an owner, which means the Application Developer is locked out of the very application they created.
Shoutout to Merill Fernando’s browser plugin Graph X-Ray for saving me a bunch of research time here – I just had to push the button in the Entra GUI and see what happens to find the right endpoint and associated Documentation.
As for Microsoft’s solution, they suggest creating an App Registration with app-level permissions of ‘Application.ReadWrite.OwnedBy’ and distributing the credentials to administrators. In my opinion, this approach isn’t practical for everyday use – not everyone is comfortable using PowerShell.
Reference: Comments on my Q&A accepted answer when I first tackled this issue
What we have learned
Since this has been quite a ride, I’ll keep it short:
- The feature is not yet suitable for production, if not obvious due to the lack of official support from Microsoft
- For scenarios requiring a one-time setup, the administrative experience is already acceptable
- Once we have to update members frequently, missing GUI makes management too cumbersome
- The inability to create apps significantly diminishes the feature’s advantages compared to Alternative Solutions
Supported Alternative Solutions and Workarounds:
- Application Owners
- Keeping track with regular audits or automation
- PIM Groups Scoped to Specific Application Objects
- Combine with the Application Developer role to allow app creations
- Covers everything except creating SAML Applications
- Automation / Enterprise Apps based on Application.ReadWrite.OwnedBy
The need for more granular permissions is clear to me. In the interim, I will use PIM Groups and develop automated app creation endpoints. Alternatively, I recommend that designated highly privileged admins create applications for their less privileged colleagues. (Cloud) Application Administrator should not be handed out freely.
Do you have thoughts on these findings or see anything I might have overlooked? I’d love to hear from you 😊. Join the discussion on my associated LinkedIn post.
If you’re interested in the things I do, follow me on LinkedIn.