Webservice returns 401 when called via ASP.NET Core Blazor Web App
08:48 19 Mar 2026

I been following the instructions for Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID which appears to be exactly what I need.

My issue is when the line “app.MapGet("/weather-forecast", () =>” was ran in “MinimalApiJwt” I got a 401 Unauthorized error.

Removing “.RequireAuthorization()“ shows the function runs without this check and adding “(ClaimsPrincipal user)” as a DI value shows user.Identity.IsAuthenticated is false.

My starting point was then this code from GitHub and the changes are very minimal from the sample, note I am using “Microsoft Entra ID” not “Microsoft Entra External ID” .

My Changes

Overall Solution

  • Updated to use slnx file format

  • Updated nuget packages

Project BlazorWebAppEntra (program.cs)

  • Added line “msIdentityOptions.ClientSecret = SecretValue;”

  • Created a few variables, set via new ReadConfig function

  • replaced place holders, based on comments for Entra ID

Project MinimalApiJwt (program.cs)

  • Comment out “.RequireAuthorization()“ as was getting 401

  • DI “(ClaimsPrincipal user)” so can check user details

  • Created a few variables, set via new ReadConfig function

  • replaced place holders, based on comments for Entra ID

Code from “BlazorWebAppEntra” (Program.cs)

using System.Security.Claims;
using Azure.Core;
using Azure.Identity;
using BlazorWebAppEntra.Client.Weather;
using BlazorWebAppEntra.Components;
using BlazorWebAppEntra.Weather;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.Distributed;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true);

string ReadConfig(string key) => builder.Configuration[$"AzureAd:{key}"] ?? throw new Exception($"{key} not set");

string TenantID = ReadConfig("TenantId");
string ClientId = ReadConfig("ClientId");
string WebAPIAppClientID = ReadConfig("WebAPIAppClientID");
string WebAPIAppClientBaseURL = ReadConfig("WebAPIAppClientBaseURL");
string SecretValue = ReadConfig("SecretValue");
string Domain = ReadConfig("Domain");

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(msIdentityOptions =>
    {
        msIdentityOptions.CallbackPath = "/signin-oidc";
        msIdentityOptions.ClientId = ClientId;
        msIdentityOptions.Domain = Domain;
        msIdentityOptions.Instance = "https://login.microsoftonline.com/";
        msIdentityOptions.ResponseType = "code";
        msIdentityOptions.TenantId = TenantID;
        msIdentityOptions.ClientSecret = SecretValue;
    })
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDownstreamApi("DownstreamApi", configOptions =>
    {
        configOptions.BaseUrl = WebAPIAppClientBaseURL;
        configOptions.Scopes = [ WebAPIAppClientID + "/Weather.Get" ];
    })
    .AddDistributedTokenCaches();


builder.Services.AddDistributedMemoryCache();

builder.Services.Configure(
    options =>
    {
        options.Encrypt = true;       
    });


builder.Services.AddAuthorization();

builder.Services.AddScoped();

var app = builder.Build();

if (app.Environment.IsDevelopment())
    app.UseWebAssemblyDebugging();
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();

app.MapGet("/weather-forecast", ([FromServices] IWeatherForecaster WeatherForecaster) =>
{
    return WeatherForecaster.GetWeatherForecastAsync();
}).RequireAuthorization();

app.MapRazorComponents()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(BlazorWebAppEntra.Client._Imports).Assembly);

app.MapGroup("/authentication").MapLoginAndLogout();

app.Run();

Code from “MinimalApiJwt” (Program.cs)

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Options;
using System.Security.Claims;

var builder = WebApplication.CreateBuilder(args);

string ReadConfig(string key) => builder.Configuration[$"AzureAd:{key}"] ?? throw new Exception($"{key} not set");
string TenantID = ReadConfig("TenantId");
string WebAPIAppClientID = ReadConfig("WebAPIAppClientID");

builder.Services.AddAuthentication()
    .AddJwtBearer("Bearer", jwtOptions =>
    {
        jwtOptions.Authority = "https://sts.windows.net/" + TenantID;
        jwtOptions.Audience = "api://" + WebAPIAppClientID;
    });

builder.Services.AddAuthorization();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApiDocument(); // Add NSwag services

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseOpenApi();
    app.UseSwaggerUi();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weather-forecast", (ClaimsPrincipal user) =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
}); //.RequireAuthorization();

app.Run();

internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

Entra ID Admin Centre

I don't have direct access to this as setup by network admin, but if any details are needed, please let me know and I can request them

Thanks for any help in advance

asp.net-core web-services microsoft-entra-id