在 ASP Net Core 中实现两个身份验证选项(令牌和证书)

jim*_*ck3 6 c# authentication certificate azure asp.net-core

[目标netcoreapp3.1]

你好呀!因此,我的 Startup.cs 中有一个受这种形式的中间件保护的 Web Api:


public void ConfigureServices(IServiceCollection services)
{
    //other services configuration
    services.AddProtectedWebApi(options => { /* config */};
    //other services configuration
}

Run Code Online (Sandbox Code Playgroud)

这将验证 Azure 颁发的 Jwt 令牌并授予对 API 的访问权限;效果很好。目前,我有一个前端 Angular 客户端网站,用户通过 Azure AD 登录。Angular 将令牌发送到我的 Web API,一切正常。

我现在想使用相同的 Web 应用程序来处理来自没有凭据但具有提前提供的客户端证书的用户的查询请求。所以基本上,我想通过 Azure 或通过客户端证书在我的 Angular 网站上进行身份验证。然后,Angular 会将这些信息跟踪到我的 web 应用程序,而该应用程序又会使用适当的方法对用户进行身份验证。

需要明确的是,我仍然希望某人能够使用他的 Azure 帐户在没有证书的情况下登录。

在这种情况下,是否有一种简单的方法可以拥有两个身份验证选项,而无需创建单独的 Web 应用程序?我在那里读了一点:https://learn.microsoft.com/en-us/aspnet/core/security/authentication/certauth ?view=aspnetcore-3.1#optical-client-certificates 但它似乎只适用于ASP.NET Core 5 的预览版,在我的情况下无法使用。

jim*_*ck3 4

希望以下内容对某人有所帮助!我最终找到了这个链接:https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme ?view=aspnetcore-3.1

它解释了如何实施多个授权策略,并且都有机会成功。以下是我经过更多研究后使用 IIS 找到的解决方案:

启动.cs

public void ConfigureServices(IServiceCollection services)
{
    //other services configuration
services.Configure<IISOptions>(options =>
            {
                options.ForwardClientCertificate = true;
            });

            services.Configure<CertificateForwardingOptions>(options =>
            {
                options.CertificateHeader = {/*your header present in client request*/};
            });
    //other services configuration
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
            {
                options.AllowedCertificateTypes =/*Whatever you need*/;
                options.Events = new CertificateAuthenticationEvents
                {
                    OnCertificateValidated = context =>
                    {

                        if ({/*CertValidationClass*/}.ValidateCertificate(context.ClientCertificate))
                        {
                            context.Success();
                        }
                        else
                        {
                            context.Fail("invalid cert");
                        }

                        return Task.CompletedTask;
                    }
                };
            });


    services.AddProtectedWebApi(options => { /* config */};
    //other services configuration
}
Run Code Online (Sandbox Code Playgroud)

{CertValidationClass} 是定制的服务或帮助程序类,用于验证我必须验证才能批准证书的所有内容。显然,您可以自己向此模板添加更多验证和操作。

我的中间件管道中已经有app.UseAuthentication(); app.UseAuthorization();,无需更改,但您必须app.UseCertificateForwarding();在这两个之前添加。

现在我只需在我想要保护的控制器上方指定我想要使用两种授权方法,就像这样,如果一个失败,它会依赖另一个并且它可以完美工作,我通过 Insomnia 发出请求进行了测试/没有令牌和有/没有证书。

MyApiController.cs

[Authorize(AuthenticationSchemes = AuthSchemes)]
    public class MyApiController
    {
        //Just add the schemes you want used here
        private const string AuthSchemes =
            CertificateAuthenticationDefaults.AuthenticationScheme; + "," +
            JwtBearerDefaults.AuthenticationScheme;
Run Code Online (Sandbox Code Playgroud)