验证多租户 .Net Core Web API 应用程序的颁发者的适当位置
Proper place to validate issuer for multi-tenant .Net Core Web API app
我正在开发一个多租户 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
时看到的一个问题是,似乎没有办法注入或传递对 dbContext 的引用,以便能够在数据库。
有没有人解决过这个问题或做过类似的事情?
您可以在 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");
}
};
哇,这让我走得很远!正如您所指出的,大多数文档都指向设置 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>();
希望对您有所帮助
更新:
过滤管道显示何时调用授权处理程序
我正在开发一个多租户 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
时看到的一个问题是,似乎没有办法注入或传递对 dbContext 的引用,以便能够在数据库。
有没有人解决过这个问题或做过类似的事情?
您可以在 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");
}
};
哇,这让我走得很远!正如您所指出的,大多数文档都指向设置 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>();
希望对您有所帮助
更新:
过滤管道显示何时调用授权处理程序