Configure Azure Entra External ID Authentication for Blazor Web App

Published: (February 7, 2026 at 02:12 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Overview

This guide explains how to configure Azure Entra External ID (the successor to Azure AD B2C) for a Blazor Web App. It targets Blazor Server apps but works with WebAssembly as well. The .NET version used is .NET 10 (latest LTS).

Prerequisites

  1. A default Workforce tenant in Azure Entra.
  2. Azure Entra admin access.
  3. .NET 10 SDK installed.

Create a Blazor Web App

dotnet new blazorserver -o MyBlazorApp

Set Interactive Render Mode to Server (or WebAssembly if preferred).

Add Required NuGet Packages

dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Identity.Web.UI

Configure Azure Entra

1. Log in to the Azure Entra admin center

Make sure you are in your default Workforce tenant (Overview → Manage Tenants).

2. External Identities

Navigate to External IdentitiesExternal Identity Providers and verify that the desired providers are enabled (defaults are usually sufficient).

3. User Flows

Create a new User Flow for sign‑up/sign‑in and select the user attributes you need.

4. (Optional) Custom Domain

If you have a custom domain, add it under Domain names and complete verification.

5. App Registration

  1. Go to App registrationsNew registration.
  2. Choose an option that allows personal accounts.
  3. (Optional) In Branding & Properties, set your logo, terms of service, and custom domain.
  4. (Optional) In Owners, add yourself as the app owner.

6. Authentication

Add a Web redirect URI:

https:///signin-oidc

Examples:

  • http://localhost:5171/signin-oidc
  • https://localhost:7215/signin-oidc

7. Certificates & Secrets

Create a new client secret and copy its value for later use.

Add Settings to appsettings.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "consumers",               // external users authentication
    "ClientId": "your_app_registration_client_id",
    "ClientSecret": "the_secret_you_generated_earlier", // use Key Vault in production
    "CallbackPath": "/signin-oidc"
  },
  "DownstreamApi": {
    "BaseUrl": "https://graph.microsoft.com/v1.0/",
    "RelativePath": "me",
    "Scopes": [
      "user.read"
    ]
  }
}

Configure Services in Program.cs

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;

// Add authentication services
builder.Services
    .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

builder.Services.AddCascadingAuthenticationState();

var app = builder.Build();

// Middleware
app.UseAuthentication();
app.UseAuthorization();

app.MapRazorComponents()
   .AddInteractiveServerRenderMode();

app.Run();

Update _Imports.razor

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

Require Authentication on Pages or Components

Add the Authorize attribute at the top of a Razor component or page:

@attribute [Authorize]

You can also specify roles, e.g., [Authorize(Roles = "Admin")].

Using AuthorizeView

AuthorizeView lets you show different UI for authenticated vs. unauthenticated users, such as login/logout buttons or hiding sensitive sections.

<AuthorizeView>
    <Authorized>
        <button @onclick="Logout">Logout</button>
    </Authorized>
    <NotAuthorized>
        <button @onclick="Login">Login</button>
    </NotAuthorized>
</AuthorizeView>

Reference Implementation

A complete sample project that demonstrates Azure Entra External ID integration is available in the Inventory Management System repository (link to be provided by the author).

0 views
Back to Blog

Related posts

Read more »

An Easy Recap of Supabase Essentials

Introduction Picture this: you're building your next project and need authentication, a database, and maybe storage. You could spend days configuring PostgreSQ...