[英]Cannot get a Blazor Server App to call a secure downstream Web API using Azure AD B2C
我使用 do.net new 創建了一個新的 blazor 服務器項目
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"
當我使用 Visual Studio 運行應用程序時,我可以使用我的 AAD B2C 用戶流登錄。 但是,當我單擊“調用 Web API”時,它會在 CallWebAPI.razor 中的await downstreamAPI.CallWebApiForUserAsync
引發異常
隨項目自動生成的 CallWebApi.razor 的 @Code 塊如下所示:
@code { 私有 HttpResponseMessage? 回復; 私有字符串? api結果;
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);
}
}
這是例外:
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.
我的 Web API 現在非常普通。
// GET: api/<SubscriberController>
[Authorize]
[HttpGet]
public IEnumerable<Subscriber> Get()
{
return subscriberRepository.GetAllAsync().Result;
}
根據我收集到的信息,Microsoft.Identity.Web 似乎正在調用 MSAL。 到目前為止,我在對此類錯誤進行故障排除時發現的所有內容都使我能夠捕獲 MSAL 異常並使用 AcquireTokenSilent。 因為我沒有直接使用 MSAL,所以我不確定我需要 go 在哪里添加此錯誤處理,或者為此添加什么。
對於它的價值,這也是我的 Program.cs
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();
我在我的環境中嘗試了這個場景。
我調用了類似下面的 controller 方法:
我的控制器.cs
[Authorize]
[HttpGet]
public IEnumerable<Subscriber> Get()
{
var user = await _api.Me.Request().GetAsync();
ViewData["ApiResult"] = user.DisplayName;
return await _api.Me.Request().GetAsync().Result;
}
收到同樣的錯誤:
MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
MicrosoftIdentityWebChallengeUserException: IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent
**On behalf flow is used while using the call with `CallWebApiForAppAsync`, which is not available for Azure AD B2C.**
請檢查此 b2c 限制 · AzureAD/microsoft-identity-web Wiki · GitHub
作為替代方案,您可以使用GetAccessTokenForUserAsync
請求下游 API 的訪問令牌
如果任何問題仍然存在,則使用異常處理程序進行處理並允許MicrosoftIdentityWebChallengeUserException
在調用用戶時處理 try-catch 塊中的異常。
try
{
// other code
...
ITokenAcquisition.GetAccessTokenForUserAsync(...)
//other code
}
catch (MicrosoftIdentityWebChallengeUserException)
{
// catch after capture happens with [AuthorizeForScopes] attribute
throw;
}
catch (Exception ex)
{
exceptionMessage = ex.Message;
}
確保授予 api 所需的權限,並且必須通過門戶或在身份驗證期間授予管理員同意。
然后撥打我的API即可成功:
參考: blazor-server-authorized-downstream-api-call-with-azure-ad-b2c
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.