验证多租户 .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
委托。
除了确保发行者存在于我的已验证发行者数据库中之外,我不想编写任何令牌验证逻辑。该逻辑应该放在IssuerValidator
或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,
;
);
我在使用 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
对吗?
顺便提一下,你有没有尝试过IssuerValidation
和ValidateIssuer = true
?我的理解是使用IssuerValidation
时必须将其设置为true,否则将永远不会调用委托。
更正它不使用IssuerValidator
,它只能传递一个再次遇到同样问题的方法。如果你设置ValidateIssuer = false
那么no,它不使用IssuerValidator
方法
那么IssuerAuthorizationHandler
什么时候被调用?如果 ValidateIssuer
为 false 并且默认情况下身份验证未验证颁发者,那么您创建的新处理程序在使用什么?
更新了我的答案,貌似是中间件运行后调用的以上是关于验证多租户 .Net Core Web API 应用程序的颁发者的适当位置的主要内容,如果未能解决你的问题,请参考以下文章
如何在 .NET Core Web 应用程序的单个实例中使用动态租户对 Azure Active Directory 中的用户进行身份验证?