我已经设置了两个租户123.onmicrosoft.com
和abc.onmicrosoft.com
。
我使用OpenIdConnectAuthenticationMiddleware
开发了一个Web应用程序来执行OpenID Connect身份验证流程。
开箱即用的中间件需要在配置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应用程序添加到租户目录以授予访问权限。
有更好的方法吗?