Coding Stephan

Let's talk App Roles

What are App roles in Microsoft Entra ID and why you should definitely be using them. Let’s talk app roles today.

Manage app roles in Entra ID

Role based access control

A lot of application work with Role based access control (rbac for short), most rbac systems define permissions and then map permissions to roles. Those roles are then assigned to users and that way you can easily check which users are allowed to do which actions.

This is very short management summary of role based access control, check out wikipedia is you want to know more.

Define permissions and map to roles

Let’s say your building a new application, during the design process you mapped all actions to permissions and now you have some standard roles pre-configured. Great you’re half way there. This is a very important part of the design process. You might have an Administrator role and a User role. Depending on how complicated your application is, you might have between 3 and 100 (or more) roles.

The roles are mostly static, but the mapping to which permissions they map is probably runtime configurable.

Map users to roles

As a developer you think you’re done, but how do you know which user has which roles? I’m a big fan of not having any user management in the application. User management should be handled outside of your application. Use a separate identity provider or even better use the already available external IDP (like Microsoft Entra ID, Okta or Auth0).

If user management is managed outside of your application, what to do with the mapping between user x and role y? You can of course create an user-to-group mapping table in your application, but that is super annoying if you have a bunch of “unknown” users coming in through an external IDP. You want to manage the users and their roles outside of your application.

Entra ID Group Claims

You can configure Entra to sent user groups as role claim. All done? No! This solution will give you the “external” group names and you’ll still have to map them to internal roles. Instead of an user-to-role map, you now need a group-to-role map. The other limitations of this method are (not limited by):

  • You’ll get all the user groups, up until 200. If the user exceeds 200, you’ll not get any roles.
  • Tokens issued through the implicit flow (which you should not use anyway), are limited to 5 groups
  • Not manageable for multi-tenant applications

Using this feature might work in some migration scenarios, but I would NEVER advise using it. There are better ways 👇

Entra ID App Roles 🥇

You have a multi-tenant application with two roles Administrator and User, since you’re targeting the Microsoft platform you are using Microsoft Entra ID for authentication. Users can login, without being known by the application prior to login the first time. This is called just-in-time (jit) provisioning. If your application need to setup stuff for this user, if happens the first time they use the application.

What about those roles. In this situation a new user comes in, but we have no idea what role this user needs in the application. You have roughly three options:

  1. Decide that user gets 0 roles, and its left to dry. No roles == no access.
  2. Each user that comes in gets the User role, meaning he/she can do basic things in the app.
  3. You create app roles and have the admins of the company manage who gets what role.

Option 1 and 2, force another user of the company with the Administrator role to “upgrade” this user to be get a new role, which is not very user friendly and just feels like extra administration. Because we are using JIT provisioning, this action cannot take place before the user logged in.

Configure App Roles

Each app registration in Microsoft Entra ID, can define on or more App Roles (for users/groups).

Manage app roles in Entra ID

To create a new app role, go to the specific app registration, click App Roles and click Create app role.

Create an app role for Users/Groups

  • Display Name the value that shows up in Entra, when assigning this role.
  • Allowed member type is this app role for Users and Groups for Applications* (see below) or for both.
  • Value is the value you get as role claim.
  • Description is the value administrators see if they hover over this role when assigning this role.

Recommendations:

  1. Do not create App Roles for both Users/Groups and Applications! You won’t be able to differentiate between delegated permissions and app permissions.
  2. Application app roles should have a value suffixed with .All
  3. Add a decent description to your app role
  4. Define them as early as possible for multi tenant applications
  5. Do not change the value after creating them, it will mess up the application if you suddenly emit another value for one of these roles.

Assign App Roles

The administrator of each company that is using your application was already able to assign this application to their users, under the Enterprise application. Now they have the option to select the role the user or group should get in your application. This decouples the which user should get what access completely from your application. Let the IT admin of the other company handle this, they probably know which user or group needs what access.

Assign an app role to a user or group

Microsoft also advises to Require assignments for third-party applications, to let’s turn that on as well.

Assign an app role to a user or group

With this configuration, user that are assigned to the application have access (and see the app in the My Apps portal) and immediately get the correct access in the application. Without the developer knowing anything about which group the external company might be using for that. Using app roles is really the future of app development. Personally I hate application that use SSO, but still require actions in the application to get me the correct access.

App Roles for Applications

I think mixing App Roles for users and groups with app roles for applications was a mistake, they serve different purposes. But from a functional perspective it makes sense.

If you want external applications to access your api as app, a.k.a. client credentials flow no user involved, you’ll need at least on App Role for Applications. In the OpenID connect specification these are called scopes and Microsoft calls them Application permissions when you’re assigning these.

To differentiate between the two, create separate app roles and never use the Both option. While you’re at it, suffix the value with .All as Microsoft does for their Graph API. When your application sees a token with some scope with that suffix it knows it is an application scope.

Resource based access control

Another therm we could abbreviate to rbac, to make things complicated. Using app roles are only suited to grant user some role to the entire application. If inside your application you would have role access to specific resources, like projects, this is not where app roles would shine.

Always check your requirements up front and do not sprinkle on security after the fact.

Series: Externalize Users

Conclusion

I just love app roles, we found this to be a super simple way to implement different roles in our multi-tenant applications, without the need to handle anything about those roles. No memberships, no nesting, no extra admin modules. And we did not have roll our own implementation for role based access control, this is very important because other parties like Microsoft did all the design for us. Having a battle tested authentication system is very important.

As with any authentication system, be sure to write (or generate) automated tests that validate the authentication behavior. I know this can be challenging, which is why I made Identity Proxy. This small docker container allows you to tests all you role based access cases with zero functional changes to your api.