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

Implement two authentication options (Token and Certificate) in ASP Net Core

[目标 netcoreapp3.1]

您好!所以我在 Startup.cs:

中有这个受这种形式的中间件保护的 Web Api

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

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

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

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

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

希望下面的内容对大家有所帮助! 我最终找到了这个 link : https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1

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

Startup.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
}

{CertValidationClass} 是一项服务或助手 class 定制来验证我必须验证的所有内容以批准证书。显然,您可以在此模板中自行添加更多验证和操作。

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

现在我只需要在我想保护的控制器上面指定我想使用两种授权方法,就像那样,如果一个失败,它会回到另一个并且它完美地工作,我测试了通过 Insomnia with/without 令牌和 with/without 证书提出请求。

MyApiController.cs

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