Search code examples
blazorazure-ad-b2cazure-ad-msal.net-8.0microsoft-entra-id

Does Msal work with Blazor V8 release? And where should the Msal components be located?


I'm trying to put together a Blazor app that uses Entra Id with a popup form for authentication. I have had some success with an old version of Blazor but I would like to do this with the release version of Blazor (8). The "split" project file has me a bit confused. I'm wondering if Msal works with Blazor V8 release as server side or client side or both? Anyone have experience or success incorporating Entra ID authentication with a Blazor server or webasm app?


Solution

  • If we are creating a new Blazor web app in .net 8 and want to integrate Azure AD, we need to change 7 files.

    In appsettings.json, adding AAD related configurations:

    "AzureAd": {
      "Instance": "https://login.microsoftonline.com/",
      "Domain": "tenant_id",
      "TenantId": "tenant_id",
      "ClientId": "aad_client_id",
      "CallbackPath": "/signin-oidc",
      "ClientSecret": "client_secret"
    }
    

    In csproj file, adding nuget packages:

    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" NoWarn="NU1605" />
        <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.0" NoWarn="NU1605" />
        <PackageReference Include="Microsoft.Identity.Web" Version="2.16.0" />
        <PackageReference Include="Microsoft.Identity.Web.UI" Version="2.16.0" />
    </ItemGroup>
    

    In Program.cs, adding related services.

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
    builder.Services.AddControllersWithViews()
        .AddMicrosoftIdentityUI();
    builder.Services.AddAuthorization(options =>
    {
        options.FallbackPolicy = options.DefaultPolicy;
    });
    // Add services to the container.
    builder.Services.AddRazorComponents()
        .AddInteractiveServerComponents();
    builder.Services.AddCascadingAuthenticationState();
    

    In _Imports.cshtml, adding @using Microsoft.AspNetCore.Components.Authorization.

    In Routes.razor, adding AuthorizeRouteView

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

    Creating LoginDisplay.razor in Pages folder.

    <AuthorizeView>
        <Authorized>
            Hello, @context.User.Identity?.Name!
            @authMessage
            <a href="MicrosoftIdentity/Account/SignOut">Log out</a>
        </Authorized>
        <NotAuthorized>
            <a href="MicrosoftIdentity/Account/SignIn">Log in</a>
        </NotAuthorized>
    </AuthorizeView>
    
    @code {
        private string authMessage = "The user is NOT authenticated.";
    
        [CascadingParameter]
        private Task<AuthenticationState>? authenticationState { get; set; }
    
        protected override async Task OnInitializedAsync()
        {
            if (authenticationState is not null)
            {
                var authState = await authenticationState;
                var user = authState?.User;
    
                if (user?.Identity is not null && user.Identity.IsAuthenticated)
                {
                    authMessage = $"{user.Identity.Name} is authenticated.";
                }
            }
        }
    }
    

    Adding LoginDisplay component into MainLayout.razor

    <div class="top-row px-4">
        <LoginDisplay />
        <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
    </div>
    

    ================== Update above ===================

    We can create a blazor app integrating Azure AD by the default template. Here's the screenshot for stand-alone blazor wsam(client side). Or we could refer to this document to learn more about how to create a standalone Blazor WebAssembly app that uses Microsoft Accounts with Microsoft Entra (ME-ID) for authentication.

    enter image description here

    But we don't have this option when choosing blazor web app.

    enter image description here

    Blazor web app is a replacement for Blazor server and Blazor wsam asp.net core hosted.

    We removed the Blazor Server template, and the ASP.NET Core Hosted option has been removed from the Blazor WebAssembly template. Both of these scenarios are represented by options when using the Blazor Web App template.

    For Blazor server in .net 8(blazor web app), we have document which mentioned:

    Server-side Blazor apps are configured for security in the same manner as ASP.NET Core apps. For more information, see the articles under ASP.NET Core security topics.