我已经设置了两个租户,123.onmicrosoft.com
并且abc.onmicrosoft.com
.
我开发了一个OpenIdConnectAuthenticationMiddleware
用于执行 OpenID Connect 身份验证流程的 Web 应用程序。
开箱即用的中间件需要在配置 OWIN 中间件时传递客户端 ID,这是我们面临的挑战。我们的 Web 应用程序使用两个绑定部署一次:123.mydomain.com
和abc.mydomain.com
.
我们想在运行时设置客户端 ID。我们目前的方法是开发一个子类并注入一个函数来在运行时收集客户端 ID,如下所示:
public class LendingMiddleware : OpenIdConnectAuthenticationMiddleware
{
private Action<IOwinContext, OpenIdConnectAuthenticationOptions> _optionBuilder = null;
public LendingMiddleware(OwinMiddleware next, IAppBuilder app,
OpenIdConnectAuthenticationOptions options,
Action<IOwinContext, OpenIdConnectAuthenticationOptions> optionBuilder = null) : base(next, app, options)
{
_optionBuilder = optionBuilder;
}
public LendingMiddleware(OwinMiddleware next, IAppBuilder app, OpenIdConnectAuthenticationOptions options) : base(next, app, options)
{
}
public override async Task Invoke(IOwinContext context)
{
_optionBuilder?.Invoke(context, Options);
await base.Invoke(context);
}
}
在启动类中,我们添加了两个中间件: UseTenantVerification 读取主机标头以加载与此租户关联的应用程序配置。LendingAuthentication 使用 LendingMiddleware 做 openid 流程,从 OpenIdConnectAuthenticationMiddleware 继承的借贷中间件
public void ConfigureAuth(IAppBuilder app)
{
//fixed address for multitenant apps in the public cloud
string authority = "https://login.microsoftonline.com/common/";
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions { });
app.UseTenantVerification();
app.UseLendingAuthentication(CreateOptions(authority), (ctx, options) =>
{
TenantConfig tc = ctx.Environment["TenantInfo"] as TenantConfig;
options.ClientId = tc.ClientId;
options.TokenValidationParameters.ValidAudience = tc.ClientId;
//ctx.ProtocolMessage.Password = tenantConfig.Secret;
});
}
TenantConfig
看起来像这样:
public TenantConfig GetTenantConfig(string httpHost)
{
IDictionary<string, TenantConfig> Tenants = new Dictionary<string, TenantConfig>();
Tenants.Add(new KeyValuePair<string, TenantConfig>("123.local", new TenantConfig
{
ClientId = "90677fe0-412c-4625-8d45-f37c14ffb456",
Secret = "[secret!]",
HostName = "123.local",
ApiResources = new Dictionary<string, ApiResourceConfig>
{
{
"TodoWebApi", new ApiResourceConfig
{
ResourceIdentifier = "https://123.onmicrosoft.com/TodoWebApiMT",
ResourceAddress = "http://TodoWebApiMT.local"
}
}
}
}));
Tenants.Add(new KeyValuePair<string, TenantConfig>("abc.local", new TenantConfig
{
ClientId = "000309f7-ac34-4fb6-a833-ef7c664e0958",
Secret = "[secret!]",
HostName = "abc.local",
ApiResources = new Dictionary<string, ApiResourceConfig>
{
{
"TodoWebApi", new ApiResourceConfig
{
ResourceIdentifier = "https://abc.onmicrosoft.com/TodoWebApiMT",
ResourceAddress = "http://TodoWebApiMT.local"
}
}
}
}));
var k = Tenants.Keys.First(item => item.Equals(httpHost));
return Tenants[k];
}
我们保留此租户想要访问的客户端 ID、应用程序密钥和 API 资源。我们目前只有一个 API 应用程序,但最终将是一些 API 应用程序将添加到租户目录以授予访问权限。
有一个更好的方法吗?