0

我们集中了一个 IdentityServer4,它将充当服务提供者,并且有多个身份提供者,如 Active Directory、Google、Facebook 以及基于每个租户的其他 SAML 提供者。即,一个服务提供者和多个身份提供者。

要从数据库加载 openId 配置,我完全遵循https://stackoverflow.com/a/56941908/2922388并且它按预期工作,现在我需要以相同的方式集成 SAML 提供程序。

我从组件空间完成了“SAMLv20.Core-evaluation”,并能够成功使用 appsettings.json 进行集成。

但我不确定如何按照https://stackoverflow.com/a/56941908/2922388中给出的方式以编程方式集成它。

这是我到目前为止所做的

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;
    }
}

这是我用来与 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"
4

1 回答 1

0

只是为了确认一下,您想动态添加 SAML 配置吗?

最好的方法是按照我们的配置指南的“实现 ISamlConfigurationResolver”部分中的描述实现 ISamlConfigurationResolver。

https://www.componentspace.com/Forums/8234/Configuration-Guide

每当需要配置时,都会调用您的 ISamlConfigurationResolver 实现。这意味着 SAML 配置是完全动态的。

于 2020-01-08T21:07:48.013 回答