ASP.NET (Blazor): Trigger windows authentication popup only on a single page

88 Views Asked by At

My Blazor webapp (ASP.NET) should consist of pages, that allow anonymous users (url/noauth) and a single page, which needs authentication (url/auth). The authentication mechanism to be used is windows authentication (which includes an automatically triggered popup for logging in, if authentication fails).

Popup: authentication popup

The desired behavior is to

  1. show the noauth page to any user
  2. show the auth page to authenticated users only (e.g. browser inside intranet)
  3. show a popup asking for windows credentials to non-authenticated users requesting auth page

My code:

Auth.razor

@page "/auth"
@attribute [Authorize]

<h3>Auth</h3>
<CascadingAuthenticationState>
    <AuthorizeView>
        <Authorized>
            <p>You are authorized</p>
        </Authorized>
        <NotAuthorized>
            <p>You are not authorized</p>
        </NotAuthorized>
    </AuthorizeView>
</CascadingAuthenticationState>

@code {

}

NoAuth.razor

@page "/noAuth"
@attribute [AllowAnonymous]

<h3>NoAuth</h3>

@code {

}

Program.cs (Version A)

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();
builder.Services.AddAuthorization();

This way the authentication check works fine, I am able to view the noauth page and the auth page shows me, that I am not authorized. However I do not have any means of authenticating/logging in (no popup is shown).

Program.cs (Version B)

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();
builder.Services.AddAuthorization(options => {
    options.FallbackPolicy = options.DefaultPolicy;
});

This way, when calling the auth page without being logged in I get a popup asking for my windows credentials (desired), however I get the same popup on the noauth page (not desired).

How can I either exclude the noauth page from the popup-showing-mechanism , or trigger the popup for the auth page?

1

There are 1 best solutions below

3
Tiny Wang On BEST ANSWER

You mentioned Blazor webapp ( in your statement, so I deduce you are now using blazor in .net 8. If we are using .net 8 for authentication, we should use builder.Services.AddCascadingAuthenticationState(); instead of <CascadingAuthenticationState>. We could see the migration guidance here.

Then the program.cs we have should like this:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    // By default, all incoming requests will be authorized according to the default policy.
    //options.FallbackPolicy = options.DefaultPolicy;
    //options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("admin"));
});
// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();
builder.Services.AddCascadingAuthenticationState();

You might notice that I comment line //options.FallbackPolicy = options.DefaultPolicy; that's because the default policy would make us sign in first before we visit any view, no matter whether we added [AllowAnonymous] attribution.

Then we could add @attribute [Authorize] to components which requiring authentication, and @attribute [AllowAnonymous] or don't add attribtue to components which doesn't require authentcation.

For example, my counter.razor and my home.razor

@page "/counter"
@using Microsoft.AspNetCore.Authorization
@rendermode InteractiveServer
@attribute [Authorize]

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>


@page "/"
<PageTitle>Home</PageTitle>

enter image description here