0
votes

Hi I am trying to implement Azure Groups based authorization in my .net core app. I have more groups like 100 to 200. I have added policies to add authorization.

services.AddAuthorization(options =>
            {   
                options.AddPolicy("GroupsCheck", policy =>
                {
                    policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
                    policy.RequireAuthenticatedUser();
                    policy.Requirements.Add(new GroupsCheckRequirement("11b250bf-76c0-4efe-99f2-2d781bae43bb")); //currently hard coded but want to include all the groups returned from MS graph
                });
            });

Then

 GraphServiceClient client = await MicrosoftGraphClient.GetGraphServiceClient();
 var groupList = await client.Users[userId].TransitiveMemberOf.Request().GetAsync();

This will return more than 100 groups. Now in policy I want to include all these groups. Is hard coding in config file all the groups will better way? Also my JWT token has only hasgroups:true rather than group ids. So how can I authorize based on groups? can someone help me to find good way? thanks

2
According to the situation, I suggest you change your project to use Azure AD application role-based authentication. We can create the custom application role for AD groups. But please note that If you want to assign app role for groups, you need to have Azure AD Premium plan. For more details, please refer to docs.microsoft.com/en-us/azure/architecture/… and stackoverflow.com/questions/58515744/… - Jim Xu
Thanks. We are planning to use groups based authorization and not role. - Niranjan
Do you have any other concerns? If you have no other concerns, could you please accept the answer? It may help more people who have similar issue - Jim Xu

2 Answers

2
votes

According to my test, if you just want to use groups based authorization, please refer to the following code:

  1. change Startup.cs
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
      .AddAzureAD(options => configuration.Bind(configSectionName, options));
  services.Configure<AzureADOptions>(options => configuration.Bind(configSectionName, options));
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
            {
options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.NameClaimType = "preferred_username";
 // Use the groups claim for populating roles
              options.TokenValidationParameters.RoleClaimType = "groups";
});
 services.AddMvc(options =>
      {
          var policy = new AuthorizationPolicyBuilder()
              .RequireAuthenticatedUser()
              .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
            })
        .SetCompatibilityVersion(CompatibilityVersion.Latest);

  1. Add the following code in the controller or method
if(User.Identity.IsAuthenticated){
   if (User.IsInRole("<group id>"))
            {
                 // do other action

            }
            else if (User?.FindFirst("_claim_names")?.Value != null)
            {

                /* call Graph API to check if the user is in the group

                     for example
                     GraphServiceClient client = await MicrosoftGraphClient.GetGraphServiceClient();
var memberOfGroups= await client.Me.TransitiveMemberOf.Request().GetAsync();


                    do
                    {
                        bool breakLoops = false;

                        foreach (var directoryObject in memberOfGroups.CurrentPage)
                        {
                            if (directoryObject is Group)
                            {
                                Group group = directoryObject as Group;
                                if (group.Id == "<group id>") {

                                    breakLoops = true;
                                    break;

                                }

                            }
                        }
                        if (breakLoops)
                        {
                            break;
                        }
                        if (memberOfGroups.NextPageRequest != null)
                        {
                            memberOfGroups = await memberOfGroups.NextPageRequest.GetAsync();
                        }
                        else
                        {
                            memberOfGroups = null;
                        }
                    } while (memberOfGroups != null);

               */


            }
            else {

                // do not have enough permissions
            }

}

For more details, please refer to the sample

2
votes

I'm working on a blazor server application and have been struggling with exactly this issue so I thought I'd post my solution here :) In the AuthorizationPolicyBuilder, call the .RequireClaim() method and specify the string "groups" and the ObjectId of your security group.

Before this works though, you have to go into your

Azure portal -> Azure Ad -> app registrations -> token configurations -> add groups claim.

Make sure you check off the checkbox in Security Groups and the Group ID checkbox in { ID, Access, SAML }

I don't know if this is best practice, but it worked for me :)

Here's the code from Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => Configuration.Bind("AzureAd", options));

        services.AddControllersWithViews(options =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .RequireClaim("groups", "<insert object id for group>")
                .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
        });

    }