在 C# .net core 中使用多个身份验证提供程序

mah*_*nka 7 c# azure-active-directory .net-core auth0

我们已经使用 AzureAd 对 .net 核心 API 进行了身份验证,然后出现了一个新要求,即使用 Auth0 对同一 API 进行身份验证,同时保持现有用户对 AzureAd 的访问。无需选择任何身份验证架构 API 应该能够使用 HTTP 标头中的授权令牌进行身份验证,令牌可以是 Auth0 或 AzureAD。

我发现几篇有用的文章设法使用它们构建了我的解决方案,我认为最好在一个地方编写最终解决方案,这样它可能会帮助遇到相同需求的其他人。

以下适用于 Startup.cs(在 ConfigureServices 方法中)

添加多个认证方案

我们需要将一个 JWT 承载认证注册为默认的认证方案。第二个注册了一个唯一的名字。

{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Audience = "dgdf7g6967-97fdgd";
            options.Authority = "https://login.microsoftonline.com/myazure.abc.com";
        })
        .AddJwtBearer("Auth0", options =>
        {
            options.Audience = "myweb.abc.com";
            options.Authority = "https://my.auth0.com";
        });
}
Run Code Online (Sandbox Code Playgroud)

然后我们需要更新默认授权策略以接受两种身份验证方案。

services.AddAuthorization(options =>
            {
                var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
                    JwtBearerDefaults.AuthenticationScheme, "Auth0");
                defaultAuthorizationPolicyBuilder =
                defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
                options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
            });
Run Code Online (Sandbox Code Playgroud)

完成后,您需要为两个模式添加 AddIdentities。我创建了单独的中间件来处理这个

MultipleSchemaAuthenticationMiddleware.cs

public async Task InvokeAsync(HttpContext context)
        {
            var principal = new ClaimsPrincipal();

            var resultAzureAD = await context.AuthenticateAsync();
            if (resultAzureAD?.Principal != null)
            {
                principal.AddIdentities(resultAzureAD.Principal.Identities);
            }
           
            var resultAuth0 = await context.AuthenticateAsync(AppHelper.Settings.Auth0.SchemaName);
            if (resultAuth0?.Principal != null)
            {
                principal.AddIdentities(resultAuth0.Principal.Identities);
            }

            context.User = principal;

            await _next(context);
        }
Run Code Online (Sandbox Code Playgroud)

并在 Startup.cs 中注册中间件(在 Configure 方法中)

app.UseMiddleware<MultipleSchemaAuthenticationMiddleware>();

Run Code Online (Sandbox Code Playgroud)

Mar*_*ion 2

在我看来你不需要MultipleSchemaAuthenticationMiddleware。当您AuthorizeAttribute在控制器/端点上使用时,在幕后的AuthorizationMiddleware实现内部,我们可以找到合并我们经过身份验证的每个模式的用户主体的逻辑(它在内部运行PolicyEvaluator)并将其分配给“Users”属性。

我在 .NET 6 上测试了它,它无需自定义中间件即可工作。

AuthorizationMiddleware实现:https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs

PolicyEvaluator 实现: https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authorization/Policy/src/PolicyEvaluator.cs

SecurityHelper 实现: https://github.com/dotnet/aspnetcore/blob/main/src/Shared/SecurityHelper/SecurityHelper.cs

正如我们在第 74 行看到的,AuthorizationMiddleware正在AuthenticateAsync执行PolicyEvaluator。接下来,PolicyEvaluator我们迭代策略中定义的每个模式并AuthenticateAsync在我们的HttpContext. 因此,在该SecurityHelper.MergeUserPrincipal方法的帮助下,我们的用户将充满没有MultipleSchemaAuthenticationMiddleware.