Blazor app with authentication requires a default authentication scheme

140 views Asked by At

I've come accross a situation where the absence of a default authentication scheme leads to an unauthorized state. If possible I want to omit the default scheme, however, it seems that the default scheme is required.

This is my setup:

I am omitting the default scheme, but adding the cookie authentication handler, which per default registers the "Cookies" scheme:

builder.Services.AddAuthentication().AddCookie();

I am adding a policy like this:

var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme)
                .Build();    
builder.Services.AddAuthorization(options =>
                {
                    options.AddPolicy("FooBla", policy);
                });

During setup I also add the required middleware before a call to MapBlazorHub:

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

I have defined a razor page (cshtml) for the login as follows:

@page "/login"
@model BlazorApp1.Pages.LoginModel
@{
}

and a codebehind like this:

 public class LoginModel : PageModel
    {
        public IActionResult OnGet()
        {
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "John Smith"),
                new Claim("sub", "John Smith"),
            };
            var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));

            var authProperties = new AuthenticationProperties
            {
                IsPersistent = true,
                IssuedUtc = DateTime.UtcNow,
                ExpiresUtc = DateTime.UtcNow.AddHours(12),
                AllowRefresh = true,
                RedirectUri = this.Url.Content("~/"),
            };

            this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, authProperties);

            return this.LocalRedirect(this.Url.Content("~/"));
        }
    }

And finally a component with an AuthorizeView component:

    @page "/counter"
    @inject ILoggerFactory LoggerFactory
    
    <PageTitle>Counter</PageTitle>
    
    <AuthorizeView Policy="FooBla">
        <Authorized>
            <h1>Counter</h1>
    
            <p role="status">Current count: @currentCount</p>
    
            <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
        </Authorized>
        <NotAuthorized>
            <h1>Not Authorized</h1>
        </NotAuthorized>
    </AuthorizeView>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount() => currentCount++;
        
    }

The App.razor looks like this:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <h1>Fooooo</h1>
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

After the login page the browser stores a cookie. However, the cookie handler seems not to get triggered when I redirect to the blazor component, therefore the AuthorizeView component renders the NotAuthorized Component.

These are my questions:

  1. Is it mandatory to provide a default scheme?
  2. Does the this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, authProperties); not work for blazor apps?
0

There are 0 answers