chadnt
chadnt

Reputation: 1135

Troubleshooting ASP.NET Core Role-based Authorization with Windows Authentication

Regarding a self-contained, server-side Blazor application hosted on IIS, we have configured the application to use Windows Authentication and role-based authorization derived from Active Directory groups.

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddAuthentication(IISDefaults.AuthenticationScheme);
    //....
}

public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
}

Within the application we use the <AuthorizeView /> component and the AuthenticationState to control access.

We have a staging environment and a production environment. Configuration of both environments is identical as far as I know except for the ASPNETCORE_ENVIRONMENT is set to Staging on the staging server.

The staging environment works as expected. Created a little diagnostic output to try to understand what's going on:

@page "/diag"

<h3>Diag</h3>

<AuthorizeView>

    <div>
        User.Identity.IsAuthenticated: @context.User.Identity.IsAuthenticated
    </div>

    <div>
        User.Identity.AuthenticationType: @context.User.Identity.AuthenticationType
    </div>

    <div>
        AuthenticationStateContext.User.Identity.Name: @context.User.Identity.Name
    </div>

    <div>
        User.IsInRole(Administrator): @context.User.IsInRole(Roles.Administrator)
    </div>

</AuthorizeView>

Roles.Administrator is a constant string matching the name of the AD group with administrators.

While logged in as a user in the Administrator group, the staging server produces the expected result:

User.Identity.IsAuthenticated: True
User.Identity.AuthenticationType: Negotiate
AuthenticationStateContext.User.Identity.Name: DOMAIN\my.name
User.IsInRole(Administrator): True

However the production server authenticates, but it does not recognize the role:

User.Identity.IsAuthenticated: True
User.Identity.AuthenticationType: Negotiate
AuthenticationStateContext.User.Identity.Name: DOMAIN\my.name
User.IsInRole(Administrator): False

The IIS application is configured for Windows Authentication to the best of my understanding. Anonymous Authentication is disabled, Windows Authentication is enabled. Windows Authentication appears to be working - but authorization is not.

I appreciate any feedback.

EDIT

Continued troubleshooting after the initial question. Opened a browser developer console for each site and compared the activity. Noticed the client pointed to the staging server only had one blazor request using a websocket url. The client pointing to the production server generated many blazor requests using http - I think this means it had downgraded to long-polling. Why was it not using websockets? After further investigation I discovered my production web server did not have the websocket module installed! After it was installed, the application behaves as expected.

I'm left to conclude that authorization for server-side blazor may not behave as expected with long-polling, but I'm not so certain as to try to answer my own question. I'll will happily close it if that what the community thinks is best. Maybe someone with a better understanding can provide a more complete answer.

Upvotes: 1

Views: 554

Answers (1)

FrankTheDank
FrankTheDank

Reputation: 317

Wish I could mark your Edit as the answer. This absolutely was the fix for me too. On Server 2016 IIS I had to install Websocket Module using the instructions here:

https://learn.microsoft.com/en-us/iis/configuration/system.webserver/websocket

Upvotes: 1

Related Questions