【发布时间】:2022-01-01 13:41:32
【问题描述】:
我正在开发一个 Blazor WASM 独立(不是 ASP.NET 核心托管)应用程序,该应用程序已与我的 B2C 租户集成以进行用户身份验证。 我能够成功地针对 B2C 进行身份验证。
在另一个 Azure 目录中,我有一个启用了身份验证的 Azure Function App。我正在使用 Microsoft 身份验证和身份验证设置来使用相同的 B2C 租户。作为测试,我可以通过在 API 请求的标头中传递 JWT 不记名令牌来确认我能够使用 auth 成功调用各种函数。 在 httpClient 中添加以下内容即可实现这一点
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "eyJ0eXAiOiJKV1QiLCJhbGciOiJS_WTAiGTyfEHuXjlFh5FOo8hBk1V7GFjzUn4TUOHIOjg3uDAaL730J8PewVvE8xyaG1MllR1JRjDz1D95bMch7QMqXZ-sRuUzvWdvBK_IkQ…");
不过,这显然只是作为一个测试而已。
我想要实现的是在进行后续 API 调用时使用初始 B2C 登录请求期间获得的 Bearer 令牌......但是我似乎无法弄清楚如何在 Blazor WASM 中执行此操作。我相信在 Blazor Server 这可以通过
var accessToken = await HttpContext.GetTokenAsync("access_token");
var refreshToken = await HttpContext.GetTokenAsync("refresh_token");
查看How to secure an Azure Function accessed by a Blazor Wasm app with Azure AD B2C? 上的文章链接我已按照列出的详细信息(注意新的“应用程序注册”和“应用程序(旧版)”之间存在差异)但运气不佳。在调用 FetchData 页面时,它似乎根本没有传递令牌。
这是我的 Program.cs 页面的副本:
using B2CBlazorWASMNotHosted;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using System.Net.Http;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// register CustomAuthorizationMessageHandler
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
// configure httpclient
// call the following code please add packageMicrosoft.Extensions.Http 3.1.0
builder.Services.AddHttpClient("ServerAPI", client =>
client.BaseAddress = new Uri("https://myfunctionapp.azurewebsites.net"))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
// register the httpclient
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("ServerAPI"));
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.LoginMode = "redirect";
options.ProviderOptions.DefaultAccessTokenScopes.Add("https://myb2ctenant.onmicrosoft.com/8f7ece0f-a4ef-4f96-9a24-fc4e2ced9504/AccessAPI");
});
await builder.Build().RunAsync();
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigationManager)
: base(provider, navigationManager)
{
ConfigureHandler(
authorizedUrls: new[] { "myfunctionapp.azurewebsites.net" },
scopes: new[] { "myb2ctenant.onmicrosoft.com/8f7ece0f-a4ef-4f96-9a24-fc4e2ced9504/AccessAPI" });
}
}
在 Azure 门户中,我目前有 2 个不同的应用程序注册。 1 个用于 Blazor WASM 应用程序身份验证,另一个用于函数应用程序。应用注册设置截图如下:
调用API的代码在这里:
var httpClient = new HttpClient();
var source = new CancellationTokenSource();
var centreguid = new Centre { centreguid = "CA8E99BC-F5B0-4A54-A8BF-C9AE9E95EE44" };
var response = await httpClient.PostAsJsonAsync("https://myfunctionapp.azurewebsites.net/api/GetArenasForCentre?", centreguid, source.Token);
string stringresponse = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<parentArenas>(stringresponse);
arenas = result.ArenaDetails;
Console.WriteLine("json output:");
如果我在 var result 上设置断点,我可以看到返回以下消息:
401 "您无权查看此目录或页面。"
有人能在这里指出我做错了什么吗?也许有更好的方法来实现这一点。
一些附加信息:
与为函数应用程序使用单独的应用程序注册相反,我还尝试使用相同的 SPA 应用程序注册,并已将函数应用程序身份验证配置为使用此应用程序注册......不幸的是,无济于事。 我还在此应用注册上设置了相同的 APIAccess 范围(老实说,我什至不确定是否需要应用范围)
【问题讨论】:
标签: azure-functions blazor azure-ad-b2c blazor-webassembly