I created a new blazor server project using dotnet new
dotnet new blazorserver --output "PlayingWithBlazor" --framework net6.0 --auth IndividualB2C --aad-b2c-instance "https://{mytenant}.b2clogin.com/" --domain "{mydomain}.onmicrosoft.com" --client-id "{myClientID}" --susi-policy-id "B2C_1_SignUp" --called-api-url "https://localhost:7042/api" --called-api-scopes "https://{mytennant}.onmicrosoft.com/a82e00f8-939d-47ab-b2f3-4e557020f729/access_as_user"
When I run the app using Visual Studio, I can log in using my AAD B2C user flow. However, when I click on "Call Web API" it throws an exception at await downstreamAPI.CallWebApiForUserAsync in CallWebAPI.razor
The @Code block for CallWebApi.razor that was autogenerated with the project looks like this:
@code { private HttpResponseMessage? response; private string? apiResult;
protected override async Task OnInitializedAsync()
{
try
{
response = await downstreamAPI.CallWebApiForUserAsync(
"DownstreamApi",
options => options.RelativePath = "/Subscriber");
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
apiResult = await response.Content.ReadAsStringAsync();
}
else
{
apiResult = "Failed to call the web API";
}
}
catch (Exception ex)
{
ConsentHandler.HandleException(ex);
}
}
Here is the Exception:
Microsoft.Identity.Web.MicrosoftIdentityWebChallengeUserException
HResult=0x80131500
Message=IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
Source=Microsoft.Identity.Web
StackTrace:
at Microsoft.Identity.Web.TokenAcquisition.<GetAuthenticationResultForUserAsync>d__16.MoveNext()
at Microsoft.Identity.Web.DownstreamWebApi.<CallWebApiForUserAsync>d__5.MoveNext()
at PlayingWithBlazor.Pages.CallWebApi.<OnInitializedAsync>d__3.MoveNext() in C:\Users\AndySchneider\source\repos\PlayingWithBlazor\Pages\CallWebApi.razor:line 33
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
My Web API is pretty plain vanilla right now.
// GET: api/<SubscriberController>
[Authorize]
[HttpGet]
public IEnumerable<Subscriber> Get()
{
return subscriberRepository.GetAllAsync().Result;
}
From what I have gathered, it looks like Microsoft.Identity.Web is calling MSAL. Everything I have found so far in troubleshooting an error like this leads me to catching MSAL exceptions and working with AcquireTokenSilent. Because I am not using MSAL directly, I am not sure where I would need to go to add this error handling, or what to add , for that matter.
For what its worth, here is my Program.cs as well
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using PlayingWithBlazor.Data;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Identity.Client;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var initialScopes = builder.Configuration["DownstreamApi:Scopes"]?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAdB2C"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddDownstreamWebApi("DownstreamApi", builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
builder.Services.AddSingleton<WeatherForecastService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();

