In the third part of this Azure AD series I will cover various features that can be utilized to implement authorization in your application. You can find previous posts here and here.

Azure supports groups and roles which are easilly transformable to ASP.NET Identity claims. If there are very refined rules driving your authorization, you can utilize Azure Graph API to get access to almost any data in directory’s possession in order to make your security desisions.

Groups in B2E

Groups are top level active directory objects, that can contain any number of users. Groups in B2E can also be nested, which unfortunately is not the case for B2C. Nesting groups can lead to some issues when using Graph API to check membership. Some Graph API calls are transitive and some or not, so asking about assignment to a group high in the tree hierarchy can give different results based on the api call of choice.

You can manage groups and user assignments in both legacy and new portals or using Graph API. In order to have groups automatically set as claims for ASP.NET identity, you need to flip the switch in application manifest file, because group claims are not being returned by default. Go to application settings in legacy Azure portal, select Manage Manifest, download file, find groupMembershipClaims and change null value to SecurityGroup. The other permitted value is All but this will return all user’s distribution lists, which for some users, in some corporations, can easilly excess the limit, which for JWT token is set to 200. As a side note: in new portal, you can just edit manifest in the browser, which is kind of nice.

If all goes well, ASP.NET Identity will contain claims with IDs of all groups user is assigned to:

Azure principal claims groups

Groups in B2C

This is all good and fine in B2E scenarios. B2C will not return groups in payload, no matter what configuration voodoo we will do. Graph API is a way to go and fortunatelly is not that hard to play with.

To query B2C Active Directory using Graph API you need a special service application, other than the one you are currently working with. Set of powershell commands required to create this azure app is described in detail in MSDN documentation. Once you have that, the following code will get the list of IDs of all groups user is assigned to:

var credential = new ClientCredential(clientId, clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync("https://graph.windows.net/", credential);

string userObjectId = ctx.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
string api = "/users/" + objectId + "/getMemberGroups";
string url = "https://graph.windows.net/" + tenant + api + "?api-version=1.6";
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
request.Content = new StringContent("{securityEnabledOnly: false}", Encoding.UTF8, "application/json");

var http = new HttpClient();
var response = await http.SendAsync(request);
return await response.Content.ReadAsStringAsync();

The above code requires some explanation. The goal is to make a POST request to Graph getMemberGroups operation, parametrized with user’s objectId - user’s unique identifier in AD. Call is protected with Bearer token, which needs to be provided in authentication header of the request. Token is obtained from Azure with use of this special credential set I mentioned in a previous paragraph. Notice also a securityEnabledOnly parameter provided in request body which is rough equivalent of groupMembershipClaims setting from json app manifest.

Please also note that you may not find objectidentifier claim on your user’s identity. It depends on B2C policy settings, so head out to new portal, navigate to Policies -> policy name -> Edit -> Application claims, and select User’s Object ID, see below:

Azure AD B2C objectid claim

Roles

There are some predefined global user roles in azure, like Global Admin or User, which you can see by going to role section in user profile tab in legacy portal. You can also define your custom roles per application scope. Roles setup is, again, tedious json edit in application manifest file. Go to your application download and edit manifest and add the following snippet in the empty roles section (adjust to your needs):

{
    "appRoles": [
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Reader",
      "id": "d2c2ade8-98f8-45fd-aa4a-6d06b947c64f",
      "isEnabled": true,
      "description": "Readers Have the ability to create tasks.",
      "value": "Reader"
    },
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Writer",
      "id": "d2c2ade8-98f8-45fd-aa4a-6d06b947c65f",
      "isEnabled": true,
      "description": "Writers Have the ability to create tasks.",
      "value": "Writer"
    }
  ]
}

You can set user in role while assigning him to an app. In legacy portal go to application, click users tab, select user and click ASSIGN button in the bottom. The roles dropdown should appear automatically. Remember that if you have only one role for your app, you will not be presented with any choice and assigned users will automaticaly have this role assigned. Roles will automatically be translated to claims in ASP.NET Identity.

Azure portal roles assignment

I haven’t found a way to assign user to a role in new portal.

M2M

That’s it for user’s authorization in azure B2E and B2C. In the next part of the series I’ll cover machine to machine authorization scenarios and topics like:

  • necessary manifest changes
  • setting permissions in Azure portal
  • working with Bearer tokens in C#