使用 Active Directory B2C 保护 Blazor WASM 应用程序和 Web API

Using Active Directory B2C to secure a Blazor WASM app and Web API

我有一个场景,我有一个通过 AD B2C 保护的 Blazor WASM(仅限客户端)应用程序。根据我已阅读的文档,我已在 AD B2C 中注册了一个应用程序(例如 BlazorApp)并将 Blazor 应用程序连接到此实例。此 Blazor 应用程序 API 调用 .NET Core Web API,其中端点是安全的(使用 [Authorize] 属性)。根据我阅读的文档,我还在 AD B2C(例如 WebApi)中注册了 Web API 并连接了 API 以连接到此实例。

我遇到的问题是,当我在 Blazor 应用程序中进行身份验证,然后通过 API 调用传递 access/id 令牌时,Web API 无法对其进行身份验证令牌(未经授权的错误响应)。当我连接 Web API 以连接到 BlazorApp 注册时,它会起作用(我猜是因为这是颁发令牌的地方)。但这似乎违背了在 AD 中将每个 app/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
    }
}

网络 API (.NET Core 3.1) - StartUp.cs (已删除敏感信息)

public void ConfigureServices(IServiceCollection services)
        {
            ...
        services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
                .AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));

            services.AddControllers();

            ...

        }

网络 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 app请求blazor app自己的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"
    },
    ...
}