问题描述
我遇到的情况是,我有一个通过AD B2C保护的Blazor WASM(仅限客户端)应用程序。根据我阅读的文档,我已经在AD B2C中注册了一个应用程序(例如BlazorApp),并将Blazor应用程序连接到该实例。此Blazor应用程序对.NET Core Web API进行API调用,在此端点上,端点受到安全保护(使用[Authorize]属性)。根据我阅读的文档,我还在AD B2C中注册了Web API(例如WebApi),并连接了该API以连接到该实例。
我遇到的问题是,当我在Blazor应用中进行身份验证,然后通过API调用传递访问/ ID令牌时,Web API无法对该令牌进行身份验证(未经授权的错误响应)。当我将Web API连接到BlazorApp注册时,它就起作用了(我猜是因为这是从那里发出令牌的)。但这似乎与在AD中将每个应用程序/ api注册为单独注册的建议背道而驰。
如何获得WebApi注册以识别BlazorApp发行的令牌?我要解决这个错误吗?我应该只连接Web API与BlazorApp实例进行对话吗?
其他信息:
Blazor WASM(客户端)-Program.cs (已删除敏感信息)
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
...
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C",options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccesstokenScopes.Add(@"https://<tenant name>.onmicrosoft.com/blazorapp/app.read");
options.ProviderOptions.DefaultAccesstokenScopes.Add(@"https://<tenant name>.onmicrosoft.com/blazorapp/app.write");
});
...
await builder.Build().RunAsync();
}
Blazor WASM(客户端)-appsettings.json (已删除敏感信息)
{
"AzureAdB2C": {
"Authority": "https://<tenant name>.b2clogin.com/<tenant name>.onmicrosoft.com/B2C_1_SignUpSignIn","ClientId": "<BlazorApp Application ID>","ValidateAuthority": false
}
}
Web API(.NET Core 3.1)-StartUp.cs (已删除敏感信息)
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
.AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C",options));
services.AddControllers();
...
}
Web API(.NET Core 3.1)-appsettings.json (已删除敏感信息)
注意:当我用BlazorApp应用程序ID替换WebApi应用程序ID时,身份验证有效
{
"AzureAdB2C": {
"Instance": "https://<tenant name>.b2clogin.com/tfp/","ClientId": "<WebAPI Application ID>","Domain": "<tenant name>.onmicrosoft.com","SignUpSignInPolicyId": "B2C_1_SignUpSignIn"
},...
}
解决方法
您的项目未使用OBO流,OBO流需要三个应用程序,特别是一个client-side
和两个api-side
,请参见here。
回到问题所在,首先,您的问题是配置范围错误,因为api-side
应用需要公开自己的api
,Blazor应用端的API
权限可以访问到api-side
,因此在api-side
上配置了对范围的访问权限,因此我们需要将https://<tenant name>.onmicrosoft.com/webapiapp/app.read
放在范围上,您的blazor应用程序仅用于配置访问权限。>
之所以有效,是因为您使用blazor应用程序来请求blazor应用程序自己的api
,这是可行的,尽管有些奇怪,但是可以请求自己。
因此对于您的项目,正确的请求应如下所示。
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
...
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C",options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add(@"https://<tenant name>.onmicrosoft.com/webapiapp/app.read");
options.ProviderOptions.DefaultAccessTokenScopes.Add(@"https://<tenant name>.onmicrosoft.com/webapiapp/app.write");
});
...
await builder.Build().RunAsync();
}
{
"AzureAdB2C": {
"Instance": "https://<tenant name>.b2clogin.com/tfp/","ClientId": "<Application ID>","Domain": "<tenant name>.onmicrosoft.com","SignUpSignInPolicyId": "B2C_1_SignUpSignIn"
},...
}