How to use the Authorize attribute for RBAC with Azure AD?

899 Views Asked by At

I have an ASP.NET Core 5 MVC hosted in an Azure AppService.

I've use Azure AD to limit access to the app to specific set of users. This has been working fine without any Authentication code or configuration in the app.

Now I'm trying to use Azure AD App Roles to limit functionality per roles. I defined App Roles in Azure AD, and assigned them to different users.

Running the App, and going to ./auth/me, I get the user access token the roles are showing as expected.

Now I thought I can only use the [Authorize(Roles = "SomeRole")] on top of ASP.NET controller actions to control access.

First trial, I get the following error when invoking the controller action with the [Authorize] attribute:

InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.

I can solve this error by adding the following call in the ConfigureServices method:

services.AddMicrosoftIdentityWebApiAuthentication(Configuration);

But now trying to invoke the controller action I get the following error:

Access Denied, you are not Authorized.

So apparently I'm missing something to link the [Authorize] attribute with the access token received, which has the correct roles.

Please advise.

1

There are 1 best solutions below

2
Tiny Wang On

This has been working fine without any Authentication code or configuration in the app

Then I'm afraid you are using azure APP service easy auth. You only need to register an Azure AD application and set it in your azure web app instance. And then all the users in your tenant can sign in with their account.

Your requirement now is that you also want to allow specific users to access your app, so you come up with an idea that you can assign roles to some of the users and let your application to validate the role. So you add services.AddMicrosoftIdentityWebApiAuthentication and [Authorize] in your code. But to be honest, that's not the easiest way to do it because you already enabled easy auth and it's better to not adding any code as well. So I'm afraid you can take a look at this document. It allows you to set a list of users who can sign in your app which configure to use the Azure ad app. If users aren't assigned to the Aad app try to sign in, they will get error information.

The steps to do it can be summarized as:

Going to Azure Active Directory -> Enterprise applications -> choose the app you used in your app -> Properties -> Assignment required? set to yes then save

Switch from Properties blade to Users and groups blade -> click add user/group -> select users which you allow them to sign in your app -> click assign

What you have done is implement by codes. You integrated Azure AD authentication into your MVC project. It can't validate user roles, and the user roles are used for api authorization. Here's a blog introducing it. The roles defined in Azure AD app is different from the asp.net core identity roles.

=====================================================

Ok I got your point, you want to set attributes like [Authorize(Policy = "mypolicy")] for different Controller method in your MVC project to restrict specific users to specific method. You want to use roles to differ the users.

Here's the solution:

  1. you have to create azure ad app roles and assign app roles to users. The app roles is different from default Azure ad user roles, app roles are used for your scenario.

  2. modify your MVC application following this sample or do what I shared below:

var builder = WebApplication.CreateBuilder(args);

// This is required to be instantiated before the OpenIdConnectOptions starts getting configured.
// By default, the claims mapping will map claim names in the old format to accommodate older SAML applications.
// 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' instead of 'roles'
// This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(builder.Configuration);
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme,options =>
{
    // The claim in the Jwt token where App roles are available.
    options.TokenValidationParameters.RoleClaimType = "roles";
});

// Adding authorization policies that enforce authorization using Azure AD roles.
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("mypolicy", policy => policy.RequireRole("Tiny.AccessEndpoint"));
});

builder.Services.AddControllersWithViews(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();

Then in the Controller, adding [Authorize] and adding [Authorize(Policy = "mypolicy")] action method. The test with a user who doesn't assign the app role will show error below.

enter image description here