Hello there,
The scenario here is, we have centralized a IdentityServer4 that will act as service provider and there are multiple identity providers like Active Directory, Google, Facebook and also other SAML providers based on each tenant. i.e., one service provider and multiple identity providers.
To load the openId configs from database I am exactly following the
https://stackoverflow.com/a/56941908/2922388 and it is working as expected for openid and now I need to integrate SAML providers in the same way.
I went through the "SAMLv20.Core-evaluation" and was able to do the integration using appsettings.json successfully. But I am not sure how to integrate it programatically as given in
https://stackoverflow.com/a/56941908/2922388.Here is what I have done so far
public class AccountController : ControllerBase
{
private readonly IOptionsMonitorCache<OpenIdConnectOptions> _openIdOptionsCache;
private readonly IOptionsMonitorCache<SamlAuthenticationOptions> _samlOptionsCache;
private readonly OpenIdConnectPostConfigureOptions _postConfigureOptions;
private readonly SamlPostConfigureAuthenticationOptions _samlPostConfigureOptions;
public AccountController(
IOptionsMonitorCache<OpenIdConnectOptions> openidOptionsCache,
IOptionsMonitorCache<SamlAuthenticationOptions> samlOptionsCache,
OpenIdConnectPostConfigureOptions postConfigureOptions,
SamlPostConfigureAuthenticationOptions samlPostConfigureOptions
)
{
_openIdOptionsCache = openidOptionsCache;
_samlOptionsCache = samlOptionsCache;
_postConfigureOptions = postConfigureOptions;
_samlPostConfigureOptions = samlPostConfigureOptions;
}
private async Task<IEnumerable<AuthenticationScheme>> LoadAuthenticationSchemesByTenant(IEnumerable<AuthenticationScheme> schemes, AuthProviderSetting tenantAuthProviderSetting)
{
dynamic configJson = JsonConvert.DeserializeObject(tenantAuthProviderSetting.tenantConfigJson);
switch (tenantAuthProviderSetting.AuthenticationType)
{
case AuthenticationTypes.OpenID:
var oidcOptions = new OpenIdConnectOptions
{
SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,
SignOutScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,
SaveTokens = true,
Authority = configJson.Authority,
ClientId = configJson.ClientId,
ClientSecret = configJson.ClientSecret,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role",
ValidateIssuer = false
}
};
_schemeProvider.AddScheme(new AuthenticationScheme(tenantAuthProviderSetting.AuthenticationScheme, tenantAuthProviderSetting.DisplayName, typeof(OpenIdConnectHandler)));
_postConfigureOptions.PostConfigure(tenantAuthProviderSetting.AuthenticationScheme, oidcOptions);
_openIdOptionsCache.TryAdd(tenantAuthProviderSetting.AuthenticationScheme, oidcOptions);
schemes = await _schemeProvider.GetAllSchemesAsync();
break;
case AuthenticationTypes.SAML:
var samlOptions = new SamlAuthenticationOptions
{
PartnerName = delegate () { return "
https://ExampleIdentityProvider"; },
SingleLogoutServicePath = "
https://localhost:44313/SAML/SingleLogoutService",// Not sure how to set other parameters here};
_schemeProvider.AddScheme(new AuthenticationScheme(tenantAuthProviderSetting.AuthenticationScheme, tenantAuthProviderSetting.DisplayName, typeof(SamlAuthenticationHandler)));
_samlPostConfigureOptions.PostConfigure(tenantAuthProviderSetting.AuthenticationScheme, samlOptions);
_samlOptionsCache.TryAdd(tenantAuthProviderSetting.AuthenticationScheme, samlOptions);
schemes = await _schemeProvider.GetAllSchemesAsync();
break;
default:
schemes = await _schemeProvider.GetAllSchemesAsync();
break;
}
return schemes;
}
}
Here is the config through which I used to statically integrate with IdentityServer
"SAML": {
"$schema": "https://www.componentspace.com/schemas/saml-config-schema-v1.0.json",
"Configurations": [
{
"LocalServiceProviderConfiguration": {
"Name": "https://IdentityServer4",
"Description": "IdentityServer4",
"AssertionConsumerServiceUrl": "http://localhost:44380/SAML/AssertionConsumerService",
"SingleLogoutServiceUrl": "http://localhost:44380/SAML/SingleLogoutService",
"LocalCertificates": [
{
"FileName": "certificates/sp.pfx",
"Password": "password"
}
]
},
"PartnerIdentityProviderConfigurations": [
{
"Name": "https://ExampleIdentityProvider",
"Description": "Example Identity Provider",
"SignAuthnRequest": true,
"SingleSignOnServiceUrl": "https://localhost:44313/SAML/SingleSignOnService",
"SingleLogoutServiceUrl": "https://localhost:44313/SAML/SingleLogoutService",
"PartnerCertificates": [
{
"FileName": "certificates/idp.cer"
}
]
}
]
}
]
},
"PartnerName": "https://ExampleIdentityProvider"
I've also raised the same in stackoverflow (https://stackoverflow.com/questions/59646417/load-dynamic-saml-schemes-for-identityserver4-using-componentspace) as well.