Share via


Azure AD : Retrieving All Users in Application Roles Programmatically

Background

Essentially there are two ways using which you can achieve this e.g. either using HTTP REST calls (Graph Api) and using Azure AD SDK. This article covers the details of second approach i.e. how we can query and retrieve all users in an application role using Azure AD managed providers.
Since we are interested in getting users from a Azure AD application role, we would need the application role Id against which we will be querying so we will first retrieve all the role Ids from an Azure AD application.

Note that this article assumes that you have basic understanding of Azure AD and application roles, if not then it is highly recommended that you go through this article before moving ahead.

Show Me the Code

Oh yes, here we go

public static  Dictionary<string, string> GetAllAppRoles()
{
    get
    {
       if (appRolesDictionary == null || appRolesDictionary.Count == 0)
       {
           appRolesDictionary = new  Dictionary<string, string>();
            string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
            Uri servicePointUri = new  Uri(("https://graph.windows.net");
            Uri serviceRoot = new  Uri(servicePointUri, tenantID);
 
            ActiveDirectoryClient activeDirectoryClient = new  ActiveDirectoryClient(serviceRoot, async () => await UserHelper.GetTokenForApplication());
             IPagedCollection<IApplication> retrievedApps = activeDirectoryClient.Applications.Where(w => w.AppId.Equals(ConfigHelper.ClientId)).ExecuteAsync().Result;
             if (retrievedApps != null)
             {
                Application adApp = (Application)retrievedApps.CurrentPage.FirstOrDefault();
                if (adApp != null)
                {
                    adApp.AppRoles.ToList().ForEach(e =>
                    {
                        appRolesDictionary.Add(e.DisplayName, e.Id.ToString());
                     });
                  }
              }
          }
 
           return appRolesDictionary;
      }
  }

The snippet above builds a dictionary with key as application role name and value as it’s Id. The ConfigHelper.Client is nothing but the Azure AD application Id which is registered and to which application roles are associated.

Now the next part, we will now be creating a method which accepts two arguments i.e. application role id and service principle Id. For those who do not know what service principle Id is, without going to technicalities we can just say in simple terms that it is the object Id present along with your Application Id in Azure AD app registration details and can be retrieved easily using Azure portal

[Image here]

Now let’s look at our core method

public static  List<IUser> GetAllUsersInAppRole(string servicePrincipalObjectId, string appRoleId)
{
     string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
     Uri servicePointUri = new  Uri("https://graph.windows.net");
     Uri serviceRoot = new  Uri(servicePointUri, tenantID);
     ActiveDirectoryClient activeDirectoryClient = new  ActiveDirectoryClient(serviceRoot, async () => await GetTokenForApplication());
 
      List<IUser> users = new  List<IUser>();
      var guidAppRoleId = Guid.Parse(appRoleId);
      var appRoleAssignmentsPaged = activeDirectoryClient.ServicePrincipals.GetByObjectId(servicePrincipalObjectId).AppRoleAssignedTo.ExecuteAsync().Result;
      var appRoleAssignments = EnumerateAllAsync(appRoleAssignmentsPaged);
 
       var userObjectIds = appRoleAssignments.Where(a => a.Id == guidAppRoleId && a.PrincipalType == "User").Select(a => a.PrincipalId.ToString()).ToList();
 
      foreach (var userObjectId in userObjectIds)
       {
          users.Add(activeDirectoryClient.Users.Where(w => w.ObjectId.Equals(userObjectId)).ExecuteAsync().Result.CurrentPage.FirstOrDefault());
       }
 
        return users;
}

There is an additional extension method we have written to enumerate all the paged collections 

public static  IEnumerable<T> EnumerateAllAsync<T>(this IPagedCollection<T> pagedCollection)
{
   return EnumerateAllAsync(pagedCollection, Enumerable.Empty<T>());
}
 
private static  IEnumerable<T> EnumerateAllAsync<T>(this IPagedCollection<T> pagedCollection, IEnumerable<T> previousItems)
{
     var newPreviousItems = previousItems.Concat(pagedCollection.CurrentPage);
 
      if (pagedCollection.MorePagesAvailable == false)
      {
            return newPreviousItems;
       }
 
        var newPagedCollection = pagedCollection.GetNextPageAsync().Result;
        return EnumerateAllAsync(newPagedCollection, newPreviousItems);
}

And that’s it, now the method call can be made quite conveniently i.e.

Dictionary<string, string> allAppRoles = GetAllAppRoles();
 
allAppRoles.TryGetValue(roleName, out  string roleId);
List<IUser> appRoleUsers = GetAllUsersInAppRole("app_object_Id",roleId)

That’s all folks, hope this will helps someone.

References

Below are few links which were referenced while creating / writing methods mentioned above

Conclusion

Though there is no direct and straight forward way to query and retrieve all the Azure AD users belonging to Azure AD Application roles, hope it will be in place in upcoming releases of Azure SDK but for now above approach works well.