In my previous post I started with the basic Azure AD App registration using PowerShell. I described how to set the HomePage URL, Reply URLs and even create an Application Key.
In this second part I’ll take you to the next level! I’ll describe how to add required permissions for your app.
Required Permissions
When your app needs access to other sources, like SharePoint Online sites or Mailboxes, you need to set permissions for your app. For example, this app can access Microsoft Graph, Windows Azure Active Directory and Office365 SharePoint Online:
And the explicit permissions set for SharePoint Online are:
Application Permissions: Your application needs to access SharePoint Online directly as itself (no user context). This type of permission requires administrator consent.
Delegated Permissions: Your application needs to access SharePoint Online as the signed-in user, but with access limited by the selected permission. This type of permission can be granted by a user unless the permission is configured as requiring administrator consent.
This can be a lot clicking if you don’t script it. So, let’s make your life much easier now!
ServicePrincipal
To add a required permission, you have to find out a couple things. First, we need to find the service principal on which the permissions are defined. And then second, we need to find the Application Permissions or the Delegated Permissions that you want to require.
To get a list of all service principals you use the cmdlet Get-AzureADServicePrincipal:
Get-AzureADServicePrincipal -All $true
If you want a specific service principal, you can filter on the DisplayName
When you store the service principal in a variable, you can then access the permissions:
$svcprincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -match "Office 365 SharePoint Online" } # Show the Application Permissions $svcprincipal.AppRoles | FT ID, DisplayName # Show the Delegated Permissions $svcprincipal.Oauth2Permissions | FT ID, UserConsentDisplayName
Now we know all available service principals and their permissions. We can use this now to set the required permissions for our app.
The tough part…
When we take a look at the cmdlet to create Azure AD Apps (New-AzureADApplication), we notice a parameter –RequiredResourceAccess is available. (https://docs.microsoft.com/en-us/powershell/module/azuread/new-azureadapplication?view=azureadps-2.0). However, this parameter takes an array of objects of type Microsoft.Open.AzureAD.Model.RequiredResourceAccess. Things will get more technical now and when you search the internet for this type of object, you may end up with some MSDN article: https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/entity-and-complex-type-reference#requiredresourceaccess-type
We need two kind of objects:
- RequiredResourceAccess (which basically represents the Service Principal)
- ResourceAccess (which basically represents the Application and Delegated Permissions)
The first object, RequiredResourceAccess, has two properties to set: ResourceAppId and ResourceAccess. The ResourceAppId is the same value of the ServicePrincipal AppId property.
$svcprincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -match "Microsoft Graph" } ### Microsoft Graph $reqGraph = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess" $reqGraph.ResourceAppId = $svcprincipal.AppId
The property ResourceAccess is a list of required permissions. We need to create those objects first.
##Delegated Permissions $delPermission1 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "0e263e50-5827-48a4-b97c-d940288653c7","Scope" #Access Directory as the signed in user ##Application Permissions $appPermission1 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "62a82d76-70ea-41e2-9197-370581804d09","Role" #Read and Write All Groups $appPermission2 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "19dbc75e-c2e2-444c-a770-ec69d8559fc7","Role" #Read and Write directory data
The first parameter value that’s been provided when creating the ResourceAccess object is the Id of the permission. The second value indicates the permission type: Delegated Permission (value= Scope) or Application Permission (value = Role).
Once permission objects are created, those can then be set on the RequiredResourceAccess object:
$reqGraph.ResourceAccess = $delPermission1, $appPermission1, $appPermission2
OMG, more GUIDs…
But how about that Permission Id value? By the GUID itself it is hard to recognize what permission it is. I think we have a couple of approaches here.
- You call the AppRoles and OAuth2Permissions properties to get the list of all available permissions and save it for later use. Use the required Id directly in your script and add some comments to your script what permission it is. I used this approach in this blog post.
- Query each permission based on the DisplayName property:
$permission = $svcPrincipal.AppRoles | ? { $_.DisplayName -match "Read and write directory data" } $appPermission1 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList $permission.Id,"Role"
However, Microsoft may update the DisplayName, since this area is growing!
- Like option 2, but now to query each permission based on the Value property.
Example:
$svcPrincipal.AppRoles | ? { $_.Value -eq "User.Read.All" }
At least this feels better to read and understand than the Id (option 1), but personally I’d like to stick with option 1, because I think those GUIDs aren’t going to change.
No, I did not forget it. Yes, we still need to provide the required permissions to the New-AzureADApplication cmdlet:
$myApp = New-AzureADApplication -DisplayName $appName -IdentifierUris $appURI -Homepage $appHomePageUrl -ReplyUrls $appReplyURLs -PasswordCredentials $PasswordCredential -RequiredResourceAccess $reqGraph
If you have multiple permissions, e.g. MS Graph and SharePoint Online, supply all permission objects as an array:
-RequiredResourceAccess @($reqGraph, reqSPO)
The complete script can be download from my Assets page. Go ahead, make your life easier now!
Summary
Azure AD App registrations can be created using PowerShell. Even the required permissions can be set by providing the RequiredResouceAccess parameter. To gather all information the Get-AzureADServicePrincipal cmdlet is of great help. Along with its properties AppRoles and OAuth2Permissions.
This is a lovely piece of work. Could you possibly expand this, and show once the app is registered how the app can be used to read a users mailbox? Problem I have is token assigning using REST
/A
This work is really awesome. It helped me a lot as I was struggling for this part. Thank you so much.
Could you please provide some information on how to Grant admin consent through PowerShell scripts.
Hi,
AFAIK this is not yet possible. Perhaps, this page can help you:
https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/31562305-ability-to-grant-permissions-via-api-or-powershell
Octavie
Hey,
Thank you so much for the information.
-Ishwinder
Great pair of articles. Very helpful. Thank you.
Through explaination and walk through guide for setting it up.
I’m in the process of rebuilding these to Az powershell modules 😀
I got it mostly done – still working on the Microsoft Graph permissions….
It really helped me to do automation for my application deployment. Thanks a lot.
I’m able to create the app registration just fine – but in the second step of assigning permissions the svcprincipal.AppRoles and oath2permissions are empty when I query my existing app registration. If i look at that same app in the browser it has permissions?
When searching for the service principal for Microsoft Graph you use “matches”
This returns a number of service principals (e.g. Linked In Microsoft Graph Connector)
I’m not sure that is intended, might be better to use -eq instead?
Instead of:
$svcprincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -match “Microsoft Graph” }
Use:
$svcprincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq “Microsoft Graph” }
By the way you, if you were using the exact names then you are correct about them changing while GUIDs are constant.
“Access Directory as signed in user” is now “Access the directory as you”
$svcprincipal.Oauth2Permissions|? {$_.ID -eq “0e263e50-5827-48a4-b97c-d940288653c7”} |FT ID, UserConsentDisplayName
Id UserConsentDisplayName
— ———————-
0e263e50-5827-48a4-b97c-d940288653c7 Access the directory as you
You don’t need to create actual Microsoft.Open.AzureAD.Model objects to pass as the -RequiredResourceAccess parameter. As a result you can simplify the creation code, by storing your permissions in json or some other similar form for easier management. (I suggest json because it makes extracting it from the app manifest easier)
e.g.
$jsonObj = ConvertFrom-Json -InputObject @”
{
‘requiredResourceAccess’: [
{
‘resourceAppId’: ‘00000003-0000-0000-c000-000000000000’,
‘resourceAccess’: [
{
‘id’: ‘e1fe6dd8-ba31-4d61-89e7-88639da4683d’,
‘type’: ‘Scope’
}
]
},
{
‘resourceAppId’: ‘00000003-0000-0ff1-ce00-000000000000’,
‘resourceAccess’: [
{
‘id’: ‘df021288-bdef-4463-88db-98f22de89214’,
‘type’: ‘Role’
}
]
}
]
}
“@
New-AzureADApplication -DisplayName “ReqTest” -RequiredResourceAccess $jsonObj.requiredResourceAccess
You can add comments to the json fragment to document which guids match which permissions. You can load the json fragment from a separate file etc…
Can we integrate an optional parameter which can have some properties of the SPN to be stored in a keyvault?