验证多租户 .Net Core Web API 应用程序的颁发者的适当位置

Posted

技术标签:

【中文标题】验证多租户 .Net Core Web API 应用程序的颁发者的适当位置【英文标题】:Proper place to validate issuer for multi-tenant .Net Core Web API app 【发布时间】:2019-05-28 02:52:19 【问题描述】:

我正在开发一个多租户 SPA 应用程序,它为数据调用后端 .Net Core Web API。前端 UI 将使用 MSAL 和 Microsoft 的 v2 通用端点针对 AAD 对用户进行身份验证并获取 id 和访问令牌。

在我的 Web API 中,我想验证颁发者,但正如 here 所述,使用公共端点提供的元数据使正常的颁发者验证无法使用。

我看到了一些可以覆盖或自定义令牌验证的地方的引用,但我不确定哪种方法更受欢迎,或者这些方法中的任何一种是否会导致不希望的副作用。

一种方法使用 JwtBearer 选项的事件:options.Events.TokenValidated,另一种方法使用 TokenValidationParameters 的 IssuerValidator 委托。

除了确保发行者存在于我的已验证发行者数据库中之外,我不想编写任何令牌验证逻辑。该逻辑应该放在IssuerValidatorTokenValidated 中吗?

我当前的代码如下所示(目前为单租户设置)

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
   .AddJwtBearer(options =>
    
       options.Authority = "https://myauthority.com";
       options.Audience = "https://myaudience.com/api/v1";
       options.TokenValidationParameters = new TokenValidationParameters
         
          ValidateIssuer = true,
          ValidIssuer = "myauthority.com",
          ValidateAudience = true,
          ValidAudience = "https://myaudience.com",
          ValidateLifetime = true,
          ValidateIssuerSigningKey = true,
        ;
    );

我在使用 IssuerValidator 时看到的一个问题是,似乎没有办法注入或传递对能够在数据库中查找租户 ID 所需的 dbContext 的引用。

有没有人解决过这个问题或做过类似的事情?

【问题讨论】:

刚刚阅读了这个dzimchuk.net/… 似乎很有帮助,并指向IssuerValidator。我了解将 dbcontext 注入那里的问题,并且当我可以靠近计算机时会创建一个答案 @matt_lethargic 您提到发布了一个答案,演示了如何在IssuerValidator 中获取 dbcontext。那还要来吗?这感觉是执行我的验证的更自然的地方。 【参考方案1】:

您可以在OnTokenValidated事件中检查,访问数据库上下文,您可以尝试:

 options.Events.OnTokenValidated = async (context) =>
   


       var dbContext = context.HttpContext.RequestServices.GetRequiredService<BloggingContext>();
       var blogs = await dbContext.Blogs.ToListAsync();

       if (!true)
       
           throw new SecurityTokenValidationException($"Tenant xxxxx is not registered");
       

   ;

【讨论】:

我猜在这种情况下我必须在TokenValidationParameters 中设置VaidateIssuer = false 以便令牌通过初始验证?对吗? @RHarris 。是的,设置 VaidateIssuer = false 我认为设置 ValidateIssuer = false 是不正确的(现在?)。在 ValidateIssuer = true 的 msal v3 中(以及像组织这样的多租户租户),默认的 IssuerValidator 将验证令牌中包含的发行者的一般结构,尽管任何格式良好的发行者都可以通过。因此,虽然设置 ValidateIssuer = true 并不能真正实现很多,但严格来说,您需要将 ValidateIssuer 设置为 false。【参考方案2】:

哇,这让我走了很长一段路!正如您指出的那样,大多数文档都指向设置 ValidateIssuer = false 并就此离开。我尝试了IssuerValidator,但我一无所获。我确实找到了IAuthorizationHandler。我使用 IMyService 代替 DBContext 创建了一个 PoC。我离开了ValidateIssuer = false

public class IssuerAuthorizationHandler : IAuthorizationHandler

    private readonly IMyService _service;

    public IssuerAuthorizationHandler(IMyService service)
    
        _service = service ?? throw new ArgumentNullException(nameof(service));
    

    public Task HandleAsync(AuthorizationHandlerContext context)
    
        if (context.User.FindFirst("iss") != null)
        
            string issuer = context.User.FindFirst("iss").Issuer;
            // do issuer validation here
        
        else
        
            // fail the authentication
            context.Fail();
        

        return Task.CompletedTask;
    

将此添加到 DI

services.AddScoped<IAuthorizationHandler, IssuerAuthorizationHandler>();

希望有帮助

更新:

显示何时调用授权处理程序的过滤器管道

【讨论】:

所以你在这种情况下根本没有使用IssuerValidation 对吗? 顺便提一下,你有没有尝试过IssuerValidationValidateIssuer = true?我的理解是使用IssuerValidation时必须将其设置为true,否则将永远不会调用委托。 更正它不使用IssuerValidator,它只能传递一个再次遇到同样问题的方法。如果你设置ValidateIssuer = false那么no,它不使用IssuerValidator方法 那么IssuerAuthorizationHandler什么时候被调用?如果 ValidateIssuer 为 false 并且默认情况下身份验证未验证颁发者,那么您创建的新处理程序在使用什么? 更新了我的答案,貌似是中间件运行后调用的

以上是关于验证多租户 .Net Core Web API 应用程序的颁发者的适当位置的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NET Core Web 应用程序的单个实例中使用动态租户对 Azure Active Directory 中的用户进行身份验证?

ASP.NET Core Web API 身份验证

基于 Multi-tenant Asp.net Core 网站中参数的 JWT 认证

.net 核心 API 中的混合身份验证

.net core 多租户框架整理

具有 ASP.NET Core 3.0 和 EF Core 的多租户应用程序