Add And Grant Permissions To Azure AD Application Programmatically

Introduction 

 
In my previous blog, we have seen how we can register an application in Azure Active Directory programmatically. Those who haven’t read my previous blog, please refer to this url Register and Azure AD App programmatically using c#.
 
After we register an app in Azure AD, we should grant permissions using admin consent. This will provide privileges to use data across the organization. So here again we will need Azure AD Admin account credentials.
In this blog, we will see how we can grant application permissions in Azure Active Directory programmatically using C# and Powershell.
 

Prerequisites

  1. Azure Active Directory Administrator account
  2. Visual Studio 2017 (I am using 2017, we can also use lower version)
  3. Powershell 5.0 or higher version.

Explanation

 
We will use the same solution we have created to register the app in Azure in my previous blog. We will create two methods named AddPermissions and GrantPermissions in Program class.
 
In the AddPermissions method again we need to log in to Azure Admin account via Powershell using Runspace as we have done to register our app previously.
 
To grant the permissions, we first need to add the permissions to our Azure application and then we will grant it.
 

Method for adding permission

 
Copy the below method in Program.cs file.
  1. public string AddPermissions() {  
  2.     //Uncomment below Install module line if you do not have AzureADPreview module already installed on your system.    
  3.     //pipeline.Commands.AddScript("Install-module AzureADPreview -Force -Scope CurrentUser;");    
  4.     pipeline.Commands.AddScript("Import-Module -Name AzureADPreview -Verbose \n");  
  5.     pipeline.Commands.AddScript("$username = '" + username + "';$password = convertTo-securestring '" + password + "' -AsPlainText -Force;$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password;Connect-AzureAD -Credential $cred;" + "Get-AzureADApplication -filter \"DisplayName eq 'PermissionApplication'\""); + "$access2 = New-Object -TypeName 'Microsoft.Open.AzureAD.Model.ResourceAccess' -ArgumentList 'cba73afc-7f69-4d86-8450-4978e04ecd1a','Scope';" + "$access3 = New-Object -TypeName 'Microsoft.Open.AzureAD.Model.ResourceAccess' -ArgumentList '970d6fa6-214a-4a9b-8513-08fad511e2fd','Scope';" + "$req.ResourceAccess = $access2,$access3;" + "$req.ResourceAppId = '00000002-0000-0000-c000-000000000000';");  
  6. pipeline.Commands.AddScript("Set-AzureADApplication -ObjectId '" + ObjectId + "' -RequiredResourceAccess @($req)");  
  7. try {  
  8.     var Endresults = pipeline.Invoke();  
  9.     if (pipeline.Error.Count > 0) {  
  10.         foreach(var err in pipeline.Error.ToString()) {  
  11.             Console.WriteLine(err);  
  12.         }  
  13.         runspace.Close();  
  14.         return "Fail";  
  15.     } else {  
  16.         runspace.Close();  
  17.         Console.WriteLine("Permissions Added Successfully");  
  18.         return "Success";  
  19.     }  
  20. catch (Exception ex) {  
  21.     return "Fail";  
  22. }  
  23. }  

Code Explanation

 
We have used Runspace and a Powershell object. Here Runspace will work as a workspace in which our Powershell script will run.
 
We have used Connect-AzureAd to connect to Azure Active Directory using our credentials. And then we have created one object named req of type Microsoft.Open.AzureAD.Model.RequiredResourceAccess. In this object we are adding property ResourceAccess with the GUID of permissions we need. Here I am adding permissions for Windows Azure Active Directory.
 
Two permissions are as follows,
  • Read all users basic profiles
  • Read and write all groups
These permissions have allocated GUID. We can find these GUID in the Azure Portal itself by checking the manifest of test applications with the same permissions.
 
And lastly we are updating our already registered application using ObjectId. We can get Object Id in Azure Portal.
 

Create Method to Grant Permissions

 
Copy the below method in Program.cs file in which we will grant permissions, which we have added in the previous method, to our Azure app.
  1. public string GrantPermissions()  
  2. {  
  3.     Runspace runspace = RunspaceFactory.CreateRunspace();  
  4.     runspace.Open();  
  5.     Pipeline pipeline = runspace.CreatePipeline();  
  6.     //Uncomment below line if you do not have AzureADPreview module already installed in your system  
  7.     //pipeline.Commands.AddScript("Install-module AzureADPreview -Force -Scope CurrentUser;");  
  8.     pipeline.Commands.AddScript("Import-Module AzureADPreview -Verbose;");  
  9.     pipeline.Commands.AddScript("Function Grant-OAuth2PermissionsToApp{$azureAppId ='" + appID + "'; \n" +  
  10.     "$username = '<Azure Global Username>'; \n" +  
  11.     "$password = convertTo-securestring '<password>' -AsPlainText -Force; \n" +  
  12.     "$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password; \n" +  
  13.     "$res = login-azurermaccount -Credential $cred; \n" +  
  14.     "$context = Get-AzureRmContext; \n" +  
  15.     "$tenantId = $context.Tenant.Id; \n" +  
  16.     "$refreshToken = @($context.TokenCache.ReadItems() | where {$_.tenantId -eq $tenantId -and $_.ExpiresOn -gt (Get-Date)})[0].RefreshToken; \n" +  
  17.     "$body = \"grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6\"; \n" +  
  18.     "$apiToken = Invoke-RestMethod \"https://login.windows.net/$tenantId/oauth2/token\" -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded'; \n" +  
  19.     "$header = @{'Authorization'='Bearer '+$apiToken.access_token;'X-Requested-With'='XMLHttpRequest';'x-ms-client-request-id'=[guid]::NewGuid();'x-ms-correlation-id'=[guid]::NewGuid();}; \n" +  
  20.     "$url = \"https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$azureAppId/Consent?onBehalfOfAll=true\";Invoke-RestMethod -Uri $url -Headers $header -Method POST -ErrorAction Stop;}");  
  21.     pipeline.Commands.AddScript("Grant-OAuth2PermissionsToApp");  
  22.     try{  
  23.         pipeline.Invoke();  
  24.         if (pipeline.Error.Count > 0){  
  25.             foreach (var err in pipeline.Error.ToString()){  
  26.                 Console.WriteLine(err);  
  27.             }  
  28.             runspace.Close();  
  29.             return "0";  
  30.         }  
  31.         else{  
  32.             runspace.Close();  
  33.             Console.WriteLine("Permissions Granted Successfully");  
  34.             return "1";  
  35.         }  
  36.     }  
  37.     catch (Exception ex){  
  38.         runspace.Close();  
  39.         return "0";  
  40.     }  
  41. }  

Code Explanation

 
We are using the API to grant permission to our Azure app. And to use API in Powershell we have created a function named Grant-OAuth2PermissionsToApp which takes ApplicationId is its parameter.
 
In this method we are again logging into Azure account using admin credentials. We are getting context of our tenant and tenant id by Get-AzureRmContext and $context.tenant.id.
 
Next we need tenant specific refresh token so we will invoke and Rest api method using Invoke-RestMethod and will pass the parameters to rest api.
 
Now we will use this Refresh token to grant added permissions. To do this we will again use Invoke-RestMethod which would grant all the permissions we have added to our Azure application and we will invoke Grant-OAutho2PermssionsToApp function.
 
We will invoke these pipeline commands in C# code which is running our powershell script.
 

Summary

 
You saw in this blog how we can automate the whole process of creating and registering an Azure AD app and also granting necessary permissions to the app using Powershell commands in our C# applications. Instead of a console application we can also create Class library which we can use in multiple projects.
 
Hope you like this blog.
 
Happy Coding!!
 
Please share your valuable feedback in the comment section below.