在 Identityserver4 .NET Core 中启用多个 AzureAd
Enable multiple AzureAd in Identityserver4 .NET Core
我正在尝试为一台身份服务器中的多个 AzureAD 启用登录功能。
这是必要的,因为多个租户需要能够通过 1 个身份服务器登录到他们自己的 AzureAD。设置这些将动态发生。
对于此示例,我对 AuthenticationBuilder 进行了扩展,它允许传递多个 AzureAd 并将它们添加到 AuthenticationBuilder。
//startup.cs
Dictionary<string, string> azure1 = new Dictionary<string, string>();
azure1.Add("name", "azure1");
azure1.Add("clientid", <azure1id>);
azure1.Add("tenantid", <azure1tenant>);
Dictionary<string, string> azure2 = new Dictionary<string, string>();
azure2.Add("name", "azure2");
azure2.Add("clientid", <azure2id>);
azure2.Add("tenantid", <azure2tenant>);
Dictionary<string, string>[] ids = { azure1, azure2 };
services.AddAuthentication()
.AddCookie()
.AddAzureAdAuthentications(ids)
//AuthenticationBuilderExtension
public static AuthenticationBuilder AddAzureAdAuthentications(this AuthenticationBuilder builder, Dictionary<string, string>[] azureAds)
{
string name = "";
string clientid = "";
string tenantid = "";
foreach (Dictionary<string, string> azuread in azureAds)
{
name = azuread.GetValueOrDefault("name");
clientid = azuread.GetValueOrDefault("clientid");
tenantid = azuread.GetValueOrDefault("tenantid");
builder.AddOpenIdConnect(name, name, options =>
{
options.Authority = $"https://login.microsoftonline.com/{tenantid}";
options.ClientId = clientid;
options.ResponseType = OpenIdConnectResponseType.IdToken;
});
}
return builder;
}
我希望上面的代码添加 2 个 azureAd 作为登录选项,这工作正常。我认为身份验证流程会保持完整。
相反,出现了 2 个问题。
- 两个登录选项都指向最后一个配置 (azure2),azure1 就消失了。这意味着最后的配置会覆盖第一个。
- 使用有效账号登录azure2时,登录identityserver失败,出现如下错误:
Exception: Correlation failed.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+d__12.MoveNext()
从字典中删除 2 个 AzureAD 中的 1 个会导致一切正常。
更新
实施最低权限回答(感谢)会产生以下结果:
它 "almost" 有效。 AzureAD 被正确识别,导致正确的流程并仅接受相应的帐户。但是现在客户端回调到identityserver后并没有登录成功。
我觉得这只是关于登录方案的一个小修改,但我真的搞不懂,因为这方面的文档非常少。
foreach (Dictionary<string, string> azuread in ids)
{
string name = azuread.GetValueOrDefault("name");
string clientid = azuread.GetValueOrDefault("clientid");
string tenantid = azuread.GetValueOrDefault("tenantid");
services.AddAuthentication(name).AddCookie($"Cookie{name}").AddOpenIdConnect(name, name, options =>
{
options.SignInScheme = $"Cookie{name}";
options.SignOutScheme = $"Cookie1{name}";
options.CallbackPath = $"/signin-{name}";
options.Authority = $"https://login.microsoftonline.com/{tenantid}";
options.ClientId = clientid;
options.ResponseType = OpenIdConnectResponseType.IdToken;
});
}
解决方案
可能没有那么难,但分享解决方案以帮助他人:
services.AddAuthentication().AddCookie($"Cookie{name}")
.AddOpenIdConnect(name, name, options =>
{
options.CallbackPath = $"/signin-{name}";
options.Authority = $"https://login.microsoftonline.com/{tenantid}";
options.ClientId = clientid;
options.ResponseType = OpenIdConnectResponseType.IdToken;
});
每个处理程序至少需要一个唯一的 CallbackPath
- 还有其他用于注销和 post 重定向的回调 - 如果您使用这些功能,也必须设置它们。
此外,身份验证方案必须是唯一的。
我正在尝试为一台身份服务器中的多个 AzureAD 启用登录功能。
这是必要的,因为多个租户需要能够通过 1 个身份服务器登录到他们自己的 AzureAD。设置这些将动态发生。
对于此示例,我对 AuthenticationBuilder 进行了扩展,它允许传递多个 AzureAd 并将它们添加到 AuthenticationBuilder。
//startup.cs
Dictionary<string, string> azure1 = new Dictionary<string, string>();
azure1.Add("name", "azure1");
azure1.Add("clientid", <azure1id>);
azure1.Add("tenantid", <azure1tenant>);
Dictionary<string, string> azure2 = new Dictionary<string, string>();
azure2.Add("name", "azure2");
azure2.Add("clientid", <azure2id>);
azure2.Add("tenantid", <azure2tenant>);
Dictionary<string, string>[] ids = { azure1, azure2 };
services.AddAuthentication()
.AddCookie()
.AddAzureAdAuthentications(ids)
//AuthenticationBuilderExtension
public static AuthenticationBuilder AddAzureAdAuthentications(this AuthenticationBuilder builder, Dictionary<string, string>[] azureAds)
{
string name = "";
string clientid = "";
string tenantid = "";
foreach (Dictionary<string, string> azuread in azureAds)
{
name = azuread.GetValueOrDefault("name");
clientid = azuread.GetValueOrDefault("clientid");
tenantid = azuread.GetValueOrDefault("tenantid");
builder.AddOpenIdConnect(name, name, options =>
{
options.Authority = $"https://login.microsoftonline.com/{tenantid}";
options.ClientId = clientid;
options.ResponseType = OpenIdConnectResponseType.IdToken;
});
}
return builder;
}
我希望上面的代码添加 2 个 azureAd 作为登录选项,这工作正常。我认为身份验证流程会保持完整。
相反,出现了 2 个问题。
- 两个登录选项都指向最后一个配置 (azure2),azure1 就消失了。这意味着最后的配置会覆盖第一个。
- 使用有效账号登录azure2时,登录identityserver失败,出现如下错误:
Exception: Correlation failed. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+d__12.MoveNext()
从字典中删除 2 个 AzureAD 中的 1 个会导致一切正常。
更新
实施最低权限回答(感谢)会产生以下结果: 它 "almost" 有效。 AzureAD 被正确识别,导致正确的流程并仅接受相应的帐户。但是现在客户端回调到identityserver后并没有登录成功。
我觉得这只是关于登录方案的一个小修改,但我真的搞不懂,因为这方面的文档非常少。
foreach (Dictionary<string, string> azuread in ids)
{
string name = azuread.GetValueOrDefault("name");
string clientid = azuread.GetValueOrDefault("clientid");
string tenantid = azuread.GetValueOrDefault("tenantid");
services.AddAuthentication(name).AddCookie($"Cookie{name}").AddOpenIdConnect(name, name, options =>
{
options.SignInScheme = $"Cookie{name}";
options.SignOutScheme = $"Cookie1{name}";
options.CallbackPath = $"/signin-{name}";
options.Authority = $"https://login.microsoftonline.com/{tenantid}";
options.ClientId = clientid;
options.ResponseType = OpenIdConnectResponseType.IdToken;
});
}
解决方案
可能没有那么难,但分享解决方案以帮助他人:
services.AddAuthentication().AddCookie($"Cookie{name}")
.AddOpenIdConnect(name, name, options =>
{
options.CallbackPath = $"/signin-{name}";
options.Authority = $"https://login.microsoftonline.com/{tenantid}";
options.ClientId = clientid;
options.ResponseType = OpenIdConnectResponseType.IdToken;
});
每个处理程序至少需要一个唯一的 CallbackPath
- 还有其他用于注销和 post 重定向的回调 - 如果您使用这些功能,也必须设置它们。
此外,身份验证方案必须是唯一的。