Skip to content

Latest commit

 

History

History
276 lines (196 loc) · 18.3 KB

File metadata and controls

276 lines (196 loc) · 18.3 KB
services platforms author level client service endpoint
active-directory
dotnet
kalyankrishna1
400
ASP.NET Core 2.x Web App
Microsoft Graph
Microsoft identity platform

Add authorization using groups & group claims to an ASP.NET Core Web app that signs-in users with the Microsoft identity platform

About this sample

Overview

This sample shows how a .NET Core 2.2 MVC Web app that uses OpenID Connect to sign in users. It also obtains the security groups the signed-in user is assigned to as a claim in their token. Security groups are a popular means to implement authorization.

Authorization in Azure AD can also be done with Application Roles, as shown in WebApp-RoleClaims. Azure AD Groups and Application Roles are by no means mutually exclusive - they can be used in tandem to provide even finer grained access control.

Build status

Scenario

This sample first leverages the ASP.NET Core OpenID Connect middleware to sign in the user. On the home page it displays the various claims that the user's ID Token contained. The ID token is used by the asp.net security middleware to build the ClaimsPrincipal, which is accessible via HttpContext.User property.

Sign in with the Microsoft identity platform

This is the fifth chapter of our tutorial. Once you understand how to receive the group memberships in a user's claims, you can also try the sample Add authorization using app roles & roles claims to an ASP.NET Core Web app thats signs-in users with the Microsoft identity platform to learn about how to use the App roles in an app using the Microsoft Identity Platform to authenticate users.

Pre-requisites:

This guide assumes that you've already went through the previous chapter of the tutorial Using the Microsoft identity platform to call the Microsoft Graph API from an An ASP.NET Core 2.x Web App. This page shows the incremental change needed to set up group membership claims and retrieve them in your app when a user signs in.

To run this sample, you'll need:

  • Visual Studio 2017 or just the .NET Core SDK
  • An Internet connection
  • A Windows machine (necessary if you want to run the app on Windows)
  • An OS X machine (necessary if you want to run the app on Mac)
  • A Linux machine (necessary if you want to run the app on Linux)
  • An Azure Active Directory (Azure AD) tenant. For more information on how to get an Azure AD tenant, see How to get an Azure AD tenant
  • A user account in your Azure AD tenant. This sample will not work with a Microsoft account (formerly Windows Live account). Therefore, if you signed in to the Azure portal with a Microsoft account and have never created a user account in your directory before, you need to do that now.

Step 1: Clone or download this repository

From your shell or command line:

Navigate to the "5-WebApp-AuthZ" folder

 cd "5-2-Groups"

Step 3: Configure your application to receive the groups claims

  1. In your application settings page on the Application Registration Portal, click on "Manifest" to open the inline manifest editor.
  2. Edit the manifest by locating the "groupMembershipClaims" setting, and setting its value to "SecurityGroup".
  3. Save the manifest.
{
  ...
  "errorUrl": null,
  "groupMembershipClaims": "SecurityGroup",
  ...
}
  1. To receive the groups claim with the object id of the security groups, make sure that the user accounts you plan to sign-in to this app is assigned to a few security groups in this AAD tenant.

To get the on-premise group's `samAccountName/mailNickName' instead of Group Ids, check out the Configure group claims for applications with Azure Active Directory (Public Preview) feature.

Step 4: Run the sample

  1. Clean the solution, rebuild the solution, and run it.

  2. Open your web browser and make a request to the app. The app immediately attempts to authenticate you via the Microsoft identity platform endpoint. Sign in with a work or school account from the tenant where you created this app.

  3. On the home page, the app lists the various claims it obtained from your ID token. You'd notice one more claims named groups. If Overage occurred, then you'd see a different claim by the name _claim_names. The Overage scenario is discussed in detail below.

  4. On the top menu, click on the signed-in user's name user@domain.com, you should now see all kind of information about yourself including your picture. Beneath that, a list of all the security groups that the signed-in user is assigned to are listed as well. All of this was obtained by making calls to Microsoft Graph. This list is useful, if an Overage occurs with this signed-in user. The overage scenario is discussed later in this article.

Did the sample not work for you as expected? Did you encounter issues trying this sample? Then please reach out to us using the GitHub Issues page.

Processing Groups claim in tokens, including handling overage

The groups claim

The object id of the security groups the signed in user is member of is returned in the groups claim of the token.

{
  ...
  "groups": [
    "0bbe91cc-b69e-414d-85a6-a043d6752215",
    "48931dac-3736-45e7-83e8-015e6dfd6f7c",]
  ...
}

Groups overage claim

To ensure that the token size doesn’t exceed HTTP header size limits, the Microsoft Identity Platform limits the number of object Ids that it includes in the groups claim.

If a user is member of more groups than the overage limit (150 for SAML tokens, 200 for JWT tokens), then the Microsoft Identity Platform does not emit the groups claim in the token. Instead, it includes an overage claim in the token that indicates to the application to query the Graph API to retrieve the user’s group membership.

{
  ...
  "_claim_names": {
    "groups": "src1"
    },
    {
   "_claim_sources": {
    "src1": {
        "endpoint":"[Graph Url to get this user's group membership from]"
        }
    }
  ...
}

An Identity Office Hours session covered Azure AD App roles and security groups, featuring this scenario and how to handle the overage claim. Watch the video Using Security Groups and Application Roles in your apps

You can use the BulkCreateGroups.ps1 provided in the App Creation Scripts folder to create a large number of groups and assign users to them. This will help test overage scenarios during development.

Order of processing the overage claim
  1. Check for the claim _claim_names with one of the values being groups. This indicates overage.

  2. If found, make a call to the endpoint specified in _claim_sources to fetch user’s groups.

  3. If none found, look into the groups claim for user’s groups.

When attending to overage scenarios, which requires a call to Microsoft Graph to read the signed-in user's group memberships, your app will need to have the Directory.Read.All for the getMemberObjects function to execute successfully.

When using the implicit_grant flow to authenticate

In case, you are authenticating using the implicit grant flow, the overage indication and limits are different than the apps using other flows.

  1. A claim named hasgroups with a value of true will be present in the token instead of the groups claim .
  2. The maximum number of groups provided in the groups claim is limited to 6. This is done to prevent the URI fragment beyond the URL length limits.

Support in ASP.NET Core middleware libraries

The asp.net middleware supports roles populated from claims by specifying the claim in the RoleClaimType property of TokenValidationParameters. Since the groups claim contains the object ids of the security groups than actual names, you'd use the group id's instead of group names. See Role-based authorization in ASP.NET Core for more info.

// Startup.cs
public static IServiceCollection AddMicrosoftIdentityPlatformAuthentication(this IServiceCollection services, IConfiguration configuration, X509Certificate2 tokenDecryptionCertificate = null)
{
        // [removed for] brevity

            // The following lines code instruct the asp.net core middleware to use the data in the "groups" claim in the Authorize attribute and User.IsInrole()
            // See https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.2 for more info.
            services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
            {
                // Use the groups claim for populating roles
                options.TokenValidationParameters.RoleClaimType = "groups";
            });
        // [removed for] brevity
}

// In code..(Controllers & elsewhere)
[Authorize(Roles = “Group-object-id")] // In controllers
// or
User.IsInRole("Group-object-id"); // In methods

About the code

The following files have the code that would be of interest to you..

  1. HomeController.cs

    1. Passes the HttpContext.User (the signed-in user) to the view.
  2. UserProfileController.cs

    1. Uses the IMSGraphService methods to fetch the signed-in user's group memberships. 1 IMSGraphService.cs, MSGraphService.cs and UserGroupsAndDirectoryRoles.cs
    2. Uses the Microsoft Graph SDK to carry out various operations with Microsoft Graph.
  3. Home\Index.cshtml

    1. This has some code to print the current user's claims
  4. UserProfile\Index.cshtml

    1. Has some client code that prints the signed-in user's information obtained from the /me, /me/photo and /memberOf endpoints.
  5. Startup.cs

    - at the top of the file, add the following using directive:
    
     using Microsoft.Identity.Web;
    • in the ConfigureServices method, replace the two following lines:

       services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
               .AddAzureAD(options => Configuration.Bind("AzureAd", options));
      
      // by this line:
      
      //This enables your application to use the Microsoft identity platform endpoint. This endpoint is capable of signing-in users both with their Work and School and Microsoft Personal accounts.
             services.AddMicrosoftIdentityPlatformAuthentication(Configuration)
                     .AddMsal(Configuration, new string[] { "User.Read", "Directory.Read.All" }) // Adds support for the MSAL library with the permissions necessary to retrieve the signed-in user's group info in case of a token overage
                     .AddInMemoryTokenCaches(); // Adds aspnetcore MemoryCache as Token cache provider for MSAL.
      
         services.AddMSGraphService(Configuration);    // Adds the IMSGraphService as an available service for this app.
  6. if you used the Powershell scripts provided in the AppCreationScripts folder, then note the extra parameter -GroupMembershipClaims in the Configure.ps1 script.

      -Oauth2AllowImplicitFlow $true `
      -GroupMembershipClaims "SecurityGroup" `
      -PublicClient $False

Community Help and Support

Use Stack Overflow to get support from the community. Ask your questions on Stack Overflow first and browse existing issues to see if someone has asked your question before. Make sure that your questions or comments are tagged with [ msal azure-active-directory].

If you find a bug in the sample, please raise the issue on GitHub Issues.

To provide a recommendation, visit the following User Voice page.

Next steps

Learn more

Contributing

If you'd like to contribute to this sample, see CONTRIBUTING.MD.

This project has adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.