Entra RBAC For Applications

Using ASP.NET I needed a way to identify users by role, these users are managed by Entra ID, the roles are configured in Entra under the registered application and the assigned to the user.

These steps assume you already have an Entra ID and an application registered with Entra, I didnt use the Entra UI but rather Visual Studio Connected Services

Entra UI Steps

MS will probably update their UI tomorrow but these steps are correct as of 15/01/2025

Create User

  1. Log into https://entra.microsoft.com/
  2. On the left select Users -> All Users -> + New User -> Crate new user
  3. Populate the required fields, these are values referenced below in this post
1
2
User principal name: carl.test
Display name: Carl Test
  1. Dont add any groups/roles here, just create

Create Roles

  1. Log into https://entra.microsoft.com/
  2. On the left select Applications -> App registrations -> select the owned application instance
  3. On the left select App roles -> + Create app role
  4. Populate the details as follows, the Value is what will be checked for in the code
1
2
3
4
Display name   | Allowed member types   | Value     | Description
-------------------------------------------------------------------
App Foo Role | Users/Groups | App.Foo | App Foo Role
App Baz Role | Users/Groups | App.Baz | App Baz Role

Created App Roles

  1. Select Overview -> Managed application in local directory (its near the top right)
  2. On the left select Users and groups -> + Add user/group
  3. Users -> click None Selected -> Check next to Carl Test and click Select
  4. Select a role -> click None Selected -> click App Foo Role and click Assign
  5. Repeat for other roles like App Baz Role

Assigned App Roles

Code Steps (Auth Policy)

Simliar to Auth Policy Checking Scope we can create Policies based claims

  1. In program.cs build the policy
1
2
3
builder.Services.AddAuthorizationBuilder()
.AddPolicy("AppFooPolicy", policy => policy.RequireRole("App.Foo"))
.AddPolicy("AppBazPolicy", policy => policy.RequireRole("App.Baz"));
  1. In the controller add the annotation
1
2
3
4
5
[Authorize(Policy = "AppFooPolicy")]
public IActionResult Index()
{
return View();
}

Alternatively just check for the Role directly

1
2
3
4
5
[Authorize(Roles = "App.Foo")]
public IActionResult Index()
{
return View();
}

Code Steps (Logic by Role)

We can confirm all the users claims by checking the context

  1. Register the ContextAccessor In program.cs
1
builder.Services.AddHttpContextAccessor();
  1. Inject IHttpContextAccessor and query all claims
1
2
3
4
5
public HomeController(ILogger<HomeController> logger, IHttpContextAccessor httpContextAccessor)
{
if (httpContextAccessor.HttpContext!.User.Identity?.IsAuthenticated == true)
{
var claims = httpContextAccessor.HttpContext!.User.Claims.ToList();
  1. This will give a key value of all claims, the ones we care about are App.Foo and App.Baz. In this case the claim is a role.

Claims

  1. You can then build a service that instead takes IHttpContextAccessor and returns true/false by role using IsInRole.

This can then programatically show/hide parts of the application or dictate logical flow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class RoleService(IHttpContextAccessor httpContextAccessor)
{
public bool HasAppFooRole()
{
if (!IsAuthenticated())
return false;

return httpContextAccessor.HttpContext!.User.IsInRole("App.Foo");
}

private bool IsAuthenticated()
{
return httpContextAccessor
.HttpContext!
.User
.Identity?
.IsAuthenticated == true;
}
}

Code Steps (Logic by Group)

This can also be done with groups using the same policy approach as above with RequireClaim

1
2
3
4
5
builder.Services.AddAuthorization(o =>
{
o.AddPolicy("UserIsInGroup", p =>
p.RequireClaim("groups", "{YOUR-GROUP-GUID}"));
})

You get the group GUID from Entra and assign it the user.

References