使用 Microsoft.Identity.Web 的 ASP.NET Core 中的多重承载身份验证方案

问题描述 投票:0回答:1

我了解可以使用自定义 JWT 提供程序在一个应用程序中添加多个身份验证方案。在以下文档中:https://github.com/AzureAD/microsoft-identity-web/wiki/Multiple-Authentication-Schemes,指出“Microsoft Identity Web 现在支持多种身份验证方案,从v. 1.11.0。”

我的问题如下:我想使用承载令牌作为对一个租户中的 Azure AD 资源和另一个租户中的 Azure AD B2C 资源进行身份验证的方法。

我尝试过以下方法:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(options =>
            {
                configuration.Bind("AzureAdB2C", options);
            }, options => 
            {
                configuration.Bind("AzureAdB2C", options);
            }, Constants.Bearer, true);

builder.Services.AddAuthentication()
            .AddMicrosoftIdentityWebApi(options =>
            {
                configuration.Bind("AzureAd", options);

                options.TokenValidationParameters.ValidAudiences = ["some-valid-audience-value-i-am-hiding-from-stack-overflow"];

            }, options => { configuration.Bind("AzureAd", options); }, Constants.Bearer, true );

这会引发以下异常:

System.InvalidOperationException:“方案已存在:承载者”

接下来,我可以将

Constants.Bearer
的名称更改为辅助值,以避免出现此异常:IE:" "Bearer2"。现在,只有第一个 AzureAdB2C 令牌可以工作,而辅助 azure 广告令牌此时会失败.

有没有办法让

AddMicrosoftIdentityWebApi
尝试从两个单独的资源解码两个单独的承载令牌?

c# asp.net-core azure-ad-b2c microsoft-identity-web azure-entra-id
1个回答
0
投票

我最终通过以下方式使其工作:

        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApi(options =>
        {
            configuration.Bind("AzureAd", options);

            options.TokenValidationParameters.ValidAudiences = [configuration["AzureAd:ClientId"]];
        }, options => { configuration.Bind("AzureAd", options); })
        .EnableTokenAcquisitionToCallDownstreamApi(_ => { })
        .AddInMemoryTokenCaches();

        builder.Services.AddAuthentication()
        .AddMicrosoftIdentityWebApi(configuration, "AzureAdB2C", "B2CScheme")
        .EnableTokenAcquisitionToCallDownstreamApi();

然后在 ASP .NET 中:

[Authorize(AuthenticationSchemes = "B2CScheme,Bearer")]

这应该允许两种模式都发挥作用。

使用 GraphQL 稍微复杂一些,但这是我的用例,所以我将其包含在这里。 将 GraphQL 与 HotChocolate 结合使用:

        serviceCollection.AddGraphQLServer()
        .AddHttpRequestInterceptor<AuthenticationInterceptor>()
        .AddAuthorization();

然后您可以在此处编写 AuthenticationInterceptor:

public class AuthenticationInterceptor : DefaultHttpRequestInterceptor
{
    public override async ValueTask OnCreateAsync(HttpContext context, IRequestExecutor requestExecutor, IQueryRequestBuilder requestBuilder, CancellationToken cancellationToken)
    {

        var result = await context.AuthenticateAsync("B2CScheme");
        if (!result.Succeeded)
        {
            result = await context.AuthenticateAsync();
        }
        //not an else here because we reassign the value of result. Just looks confusing
        if (result.Succeeded)
        {
            context.User = result.Principal;
        }
        await base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.