Is there a way to Authenticate a user before downloading the client side Blazor app?

Viewed 262

I am currently working on a Blazor web assembly project that is core hosted. The project is split up into three parts, Client, Server and Shared. The way I understand it is that when a user hits the web address they will download the client side package and run it on their web browser. I would like to know if there is a way to Authenticate a user before they download the client side package?

I have successfully implemented a login process on the client side using the microsoft documentation: Secure an ASP.NET Core Blazor WebAssembly hosted app with Azure Active Directory

but I would like to take it a step further and see if I can authenticate a user before downloading the client side package.

I have spent most of my time adding authentication code to Server.Startup.cs assuming that when a user navigates to my website they would make a request to the server for the client side package.

Has anyone tried doing anything like this? Thanks for any advice

2 Answers

I just figured out how to do this in .NET 7.0 RC1 (I don't see why it wouldn't work in 5.0 and 6.0 too, but haven't tested). So far it seems to work, but will see if I come across any issues...

In Program.cs:

// so I can access login page static assets. See extension method below
app.UseStaticAlwaysWhenPathsUniversal();

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

// restrict Blazor WASM client to users in specific role(s). See extension method below
app.UseRestrictPagesForNonPrivilegedUsers(Authentication.LoginPath);
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
/// <summary>
/// I don't want Blazor WASM accessible (at all, not even loadable) before logging in as employee user, but still make static assets
/// accessible to identity pages (e.g. login). In the future we may have customers logging in but they should not
/// be able to access Blazor WASM client.
/// </summary>
/// <param name="app">The web application</param>
public static void UseStaticAlwaysWhenPathsUniversal(this WebApplication app)
{
    app.UseWhen(
        AlwaysAllowStaticContent, // see method below
        a => a.UseStaticFiles()
    );
}
/// <summary>
/// Redirect to specified page whenever non-privileged user tries to access an address that is not allowed.
/// Use for customers in the future. Don't allow them to access Blazor WASM client.
/// </summary>
/// <param name="app">The web application</param>
/// <param name="redirectTo">The path to redirect to if the logged in user tries to access a path
/// that is not in 'allowedPaths'</param>
public static void UseRestrictPagesForNonPrivilegedUsers(this WebApplication app, string redirectTo)
{
    app.Use(async (context, next) =>
    {
        var isEmployee = context.User.HasClaim(claim => claim.Type == ClaimTypes.Role && claim.Value == "Employee");
        if (isEmployee || AlwaysAllowStaticContent(context))
        {
            await next.Invoke();
            return;
        }

        context.Response.Redirect(redirectTo);
    });
}
private static bool AlwaysAllowStaticContent(HttpContext context)
{
    return context.Request.Path.StartsWithSegments("/connect") || // my login/logout pages start with /connect
           context.Request.Path.StartsWithSegments("/_content") ||
           context.Request.Path.StartsWithSegments("/lib") ||
           context.Request.Path.StartsWithSegments("/favicon.ico");
}
Related