Search code examples
.net-coreasp.net-identityblazorblazor-server-side.net-core-3.1

Get authenticated user from Middleware class in Blazor app


I have a server sided Blazor app. Every user must be authenticated when he wants to visit a page. For this the user is redirected to an "identity server" login page. When the user logs in with the correct credentials, he is then redirected back to the Blazor app.

I have setup my Blazor app with CascadingAuthenticationState, so that I can access the User object and its claims inside my Blazor pages.

This goes something like this inside a component:

[CascadingParameter]
private Task<AuthenticationState> AuthenticationStateTask { get; set; }
...
... 
var authState = await AuthenticationStateTask;
var claims = authState.User.Claims; // Works fine.

When I do it like this I have access to the users claims.

So far so good.

But I also have a middleware class where I need to access the user claims.

public async Task InvokeAsync(HttpContext context)
{
    if (context?.User?.Claims != null && context.User.Claims.Any())
    {
        Console.WriteLine("aaa");
    }

    // Call the next delegate/middleware in the pipeline
    await _next(context);
}

But for some reason the User claims are always empty.

Why is the User.Claims object from inside my Blazor component filled with all the claims, but are they empty when I access them through the HttpContext object?


Solution

  • The order of registering Middleware is critical. This is something I've been personally running into a lot lately in my own projects as well - And yet, there are no warnings if you configure them out-of-order.

    Quote from Microsoft docs on Middleware order:

    The order that middleware components are added in the Startup.Configure method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is critical for security, performance, and functionality.

    It seems you are calling your Middleware before the .NET Core authentication middleware, and therefor your User object is null - or lacks claims.

    Place your app.UseMiddleware<T> after app.UseAuthentication() and app.UseAuthorization().