2

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

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

我已经看到对几个可以覆盖或自定义令牌验证的地方的引用,但我不确定哪个是首选,或者这些方法中的任何一个是否会导致不希望的副作用。

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

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

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

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,
        };
    });

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

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

4

2 回答 2

2

您可以检查一下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");
       }

   };
于 2019-01-02T07:49:15.007 回答
1

哇,所以这让我走了很长一段路!正如您指出的那样,大多数文件都指向设置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>();

希望这有帮助

更新:

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

核心管道

于 2019-01-03T16:21:15.850 回答