Asp.net core 如何动态设置OpenIdConnect中间件选项的权限?

Asp.net core 如何动态设置OpenIdConnect中间件选项的权限?,asp.net-core,openid-connect,Asp.net Core,Openid Connect,我们有多个租户,他们使用不同的权限(他们自己的,而不仅仅是标准提供商)。虽然我知道如何动态设置clientId和secret,但我不知道如何设置权限。它在启动期间设置一次,之后不能更改(或者看起来是这样) 由于我们有很多租户,我们不希望在启动时注册所有租户,我们也不希望在添加租户时要求重新启动 有什么建议我该怎么做?我很想使用现有的中间件,但如果不可能,我可以自己编写 谢谢你的建议 Asp.NET核心模型假定每个处理程序实例有一个上游权限。我的Saml2组件在一个处理程序中支持多个上游IDP,当

我们有多个租户,他们使用不同的权限(他们自己的,而不仅仅是标准提供商)。虽然我知道如何动态设置clientId和secret,但我不知道如何设置权限。它在启动期间设置一次,之后不能更改(或者看起来是这样)

由于我们有很多租户,我们不希望在启动时注册所有租户,我们也不希望在添加租户时要求重新启动

有什么建议我该怎么做?我很想使用现有的中间件,但如果不可能,我可以自己编写


谢谢你的建议

Asp.NET核心模型假定每个处理程序实例有一个上游权限。我的Saml2组件在一个处理程序中支持多个上游IDP,当该假设不再成立时,它在系统的其余部分中存在缺陷

在Asp.NET Core中,可以在运行时添加/删除提供程序,而无需重新启动。所以我建议找一个基于这个的模型


如果您希望一个处理程序具有每个请求的权限设置,我认为需要一个自定义处理程序-Microsoft的默认实现不支持该设置。

虽然有点棘手,但这绝对是可能的。下面是一个简化示例,使用MSFT OIDC处理程序、自定义监控器和基于路径的租户解析:

实现租户解析逻辑。例如:
公共类租户提供者
{
专用只读IHttpContextAccessor\u httpContextAccessor;
公共租户提供程序(IHttpContextAccessor httpContextAccessor)
=>\u httpContextAccessor=httpContextAccessor;
公共字符串GetCurrentTenant()
{
//此示例使用路径库作为租户。
//你可以用你自己的逻辑来代替它。
字符串tenant=\u httpContextAccessor.HttpContext.Request.PathBase;
if(string.IsNullOrEmpty(租户))
{
租户=“默认”;
}
归还承租人;
}
}
public void配置(IApplicationBuilder应用程序)
{
app.Use(下一步=>context=>
{
//此代码段使用硬编码的解析逻辑。
//在现实世界的应用程序中,你会想要自定义它。
if(context.Request.Path.StartsWithSegments(“/fabrikam”,out-PathString-Path))
{
context.Request.PathBase=“/fabrikam”;
context.Request.Path=路径;
}
返回下一个(上下文);
});
app.UseAuthentication();
app.UseMvc();
}
实现自定义的
IOptionsMonitor
公共类OpenIDConnectOptions提供程序:IOptionsMonitor
{
私有只读ConcurrentDictionary\u缓存;
私有只读IOptionsFactory\u optionsFactory;
私有只读租户Provider\u租户Provider;
公共OpenIdConnectOptionsProvider(
IOPTIONS工厂选项工厂,
租户提供商(租户提供商)
{
_缓存=新的ConcurrentDictionary();
_选项工厂=选项工厂;
_租户提供者=租户提供者;
}
public OpenIdConnectOptions CurrentValue=>Get(Options.DefaultName);
公共OpenIdConnectOptions获取(字符串名称)
{
var tenant=_tenantProvider.GetCurrentTenant();
Lazy Create()=>新建Lazy(()=>_optionsFactory.Create(name));
返回_cache.GetOrAdd((名称,租户),=>Create()).Value;
}
公共IDisposable OnChange(操作侦听器)=>null;
}
实现自定义
IConfigureNamedOptions
公共类OpenIDConnectOptions初始值设定项:IConfigureNamedOptions
{
专用只读IDataProtectionProvider\u dataProtectionProvider;
私有只读租户Provider\u租户Provider;
公共OpenIDConnectOptions初始值设定项(
IDataProtectionProvider dataProtectionProvider,
租户提供商(租户提供商)
{
_dataProtectionProvider=dataProtectionProvider;
_租户提供者=租户提供者;
}
public void配置(字符串名称、OpenIdConnectOptions选项)
{
如果(!string.Equals(name,OpenIdConnectDefaults.AuthenticationScheme,StringComparison.Ordinal))
{
返回;
}
var tenant=_tenantProvider.GetCurrentTenant();
//创建特定于租户的数据保护提供程序以确保
//其他租户无法读取/解密加密状态。
options.DataProtectionProvider=\u DataProtectionProvider.CreateProtector(租户);
//其他特定于租户的选项,如options.Authority,可以在此处注册。
}
public void配置(OpenIdConnectOptions选项)
=>Debug.Fail(“不应调用此基础结构方法”);
}
在DI容器中注册服务:
public void配置服务(IServiceCollection服务)
{
// ...
//注册OpenID连接处理程序。
services.AddAuthentication()
.AddOpenIdConnect();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
}

使用具有IdentityServer4标识的联合网关签出。这将允许单个授权机构(IdentityServer4)处理外部身份验证或多租户要求。感谢您的输入Anders,您总是非常有帮助!我想我在用你的组件实现SAML支持后被宠坏了,我只是认为这也很简单:D我从@Pinpoint获得了建议,很抱歉回复太晚,花了一些时间让其他部分正常工作,但我想我有一个基于你回复的工作示例。我会尽快发布完成的版本。非常感谢。这太棒了。我要添加的唯一建议是使用app.UsePathBase(新路径字符串(“/fabrikam”))。这允许您在控制器中使用正常路由,因为它会忽略此前缀。谢谢您提供的详细信息。基于你的方法,我已经为JWTBearner做了工作。你还有其他想法吗