This is the first part of a series of blog posts related to Azure AD best practices. They are all related to a talk I gave at Tech Days Finland as well as in the Microsoft Identity Developer Community Office Hours.

In this part our topic is the usage of groups versus application roles in Azure AD. First off, using either is basically fine. They both have their pros and cons. I prefer application roles over groups in general, but it isn't such an issue if you do use groups.

You can find sample apps for both approaches here:

Using groups for authorization

You can use groups quite easily in Azure AD. Create a group, assign some members to it, and then you can query who the members are at runtime using Microsoft Graph API. Alternatively you can ask what groups a user is a member of.

Now if you search online for "azure ad authorize by group", you will surely find this sample app. In this app, you are introduced to "group claims". Essentially you can change one property in your application's manifest like this:

{
  "groupMembershipClaims": "SecurityGroup"
}

And as a result you get group ids in the token after a user logs in like this:

{
  "groups": ["1ce9c55a-9826-4e32-871c-a8488144bb32"]
}

This is kind of nice. Now we can very easily make authorization rules in our app just by checking this one claim. And we don't need to make any calls to Microsoft Graph API, right?

What's the catch?

Well, tokens have size limitations. If a token is too big, it might not be possible to submit it in an HTTP header. So there are restrictions to this feature. You can only have max 200 group ids in a JSON Web Token.

What happens if a user is a member of more than 200 groups? You won't get any group ids in the token. Instead, you'll get claims that say "you should fetch these from this API":

{
  "_claim_names": {
    "groups": "src1"
  },
  "_claim_sources": {
    "src1": {
      "endpoint": "https://graph.windows.net/e67aa680-aaaa-aaaa-aaaa-dd25f3e75fc5/users/016a44bf-aaaa-aaaa-aaaa-dbe40a2f60b6/getMemberObjects"
    }
  }
}

Leading to you having to handle this edge case and querying the Graph API anyway.

If you do use groups for role assignments, I'd recommend just querying the Graph API over group claims.

This downside of group claims isn't actually the reason I don't like using groups. My main reason is that using groups often leads to a situation where an admin cannot know what access the user might have. They are a member of 500 groups, and some of those might give them some access, maybe. There is no connection in Azure AD that would say this group gives them this access in this application. The only people who know are the developers of that specific app.

Using application roles for authorization

Now let's look at my preferred approach. In Azure AD, you can define roles in your application's manifest that can be assigned to users and groups. Here is an example:

{
  "appRoles": [
    {
      "allowedMemberTypes": ["User"],
      "description": "Administrators can access Admin-only section",
      "displayName": "Administrators",
      "id": "d1613ef0-097a-44a0-b1d2-c13c02231a97",
      "isEnabled": true,
      "value": "admin"
    }
  ]
}

After defining the role, you can find the Enterprise app for your application (also known as the service principal), and assign roles to users.

Now once the user logs in, you'll get their roles in a claim:

{
  "roles": ["admin"]
}

It's pretty simple to setup authorization for this and no Graph API queries will be required.

With this approach, there is now an explicit link between a user and the application. An admin can thus find out what applications the user can access. Not necessarily what they can do in those applications, but at least that they have some access.

Previously I thought there was a downside that you can only assign a single role to a user. This is no longer the case. You can assign multiple roles to a user or group. Thanks for correcting this Florian Eckert! Role assignment to groups does require paid licenses (at least Basic) for all of the group members.

Summary

I consider app roles better for the visiblity it gives administrators, but using groups does not pose security risks as long as you check for group memberships correctly. If you have opinions on either approach, I'd love to hear them :)