没有实体 ID "http://stubidp.kentor.se/Metadata" 的 Idp 在 Kentor 身份验证服务中发现错误

No Idp with entity id "http://stubidp.kentor.se/Metadata" found error in Kentor Auth Services

我们需要启用 SAML SSO 登录到我的应用程序。我的应用程序是 Angular JS + Asp.Net Web API 解决方案。我的应用程序已经使用 Owin Bearer Authentication 作为授权模型。

启用 Saml SSO 我正在试验 Kentor Auth Services. But I'm facing an issue when the Idp calls my webapi. The kentor service throws The given key was not present in the dictionary. error. Im using http://stubidp.kentor.se/ 以测试实施。下面是我启动时的 Saml 配置 class

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);
            ConfigureOAuth(app);

            var config = new HttpConfiguration();
            WebApiConfig.Register(config);
            app.UseWebApi(config);

            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            GlobalConfiguration.Configuration.MessageHandlers.Add(new CachingHandler(GlobalConfiguration.Configuration));
        }
        public void ConfigureOAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            var oAuthServerOptions = new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/Auth/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                Provider = new JobPulseAuthorizationServerProvider()
            };
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    // Enables the application to validate the security stamp when the user logs in.
                    // This is a security feature which is used when you change a password or add an external login to your account.  
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                            validateInterval: TimeSpan.FromMinutes(30),
                            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ExternalCookie))
                }
            });
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            // Token Generation
            //app.UseOAuthAuthorizationServer(oAuthServerOptions);
            //app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
            app.UseKentorAuthServicesAuthentication(CreateAuthServicesOptions());
        }

        private static KentorAuthServicesAuthenticationOptions CreateAuthServicesOptions()
        {
            var spOptions = GetServiceProviderOptions();
            var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = spOptions
            };

            var idp = new IdentityProvider(new EntityId("~/App_Data/KentorIDPMetadata.xml"), spOptions)
            {
                AllowUnsolicitedAuthnResponse = true,
                Binding = Saml2BindingType.HttpRedirect,
                SingleSignOnServiceUrl = new Uri("http://stubidp.kentor.se/")
            };

            idp.SigningKeys.AddConfiguredKey(
                    new X509Certificate2(fileName: HostingEnvironment.MapPath(
                                    "~/App_Data/Kentor.AuthServices.StubIdp.cer")));

            authServicesOptions.IdentityProviders.Add(idp);

            return authServicesOptions;
        }

        private static SPOptions GetServiceProviderOptions()
        {
            var cultureInfo = CultureInfo.GetCultureInfo("en-US");
            var organization = new Organization
            {
                Names = { new LocalizedName("Kentor", cultureInfo) },
                DisplayNames = { new LocalizedName("Kentor IT AB", cultureInfo) },
                Urls = { new LocalizedUri(new Uri("http://www.kentor.se"), cultureInfo) }
            };
            var spOptions = new SPOptions
            {
                EntityId = new EntityId("http://localhost:53390/AuthServices/acs"),
                ReturnUrl = new Uri("http://localhost:53390/Account/ExternalLoginCallback"),
                Organization = organization
            };
            spOptions.Contacts.Add(new ContactPerson
            {
                Type = ContactType.Technical,
                EmailAddresses = { "authservices@example.com" }
            });

            spOptions.Contacts.Add(new ContactPerson
            {
                Type = ContactType.Support,
                EmailAddresses = { "support@example.com" }
            });
            var attributeConsumingService = new AttributeConsumingService("AuthServices")
            {
                IsDefault = true,
                RequestedAttributes =
                {
                    new RequestedAttribute("urn:someName")
                    {
                        FriendlyName = "Some Name",
                        IsRequired = true,
                        NameFormat = RequestedAttribute.AttributeNameFormatUri
                    },
                    new RequestedAttribute("Minimal")
                }
            };
            spOptions.AttributeConsumingServices.Add(attributeConsumingService);

            spOptions.ServiceCertificates.Add(new X509Certificate2(
                    AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/App_Data/Kentor.AuthServices.Tests.pfx"));

            return spOptions;
        }

    }

错误的堆栈跟踪

[KeyNotFoundException: The given key was not present in the dictionary.]
   System.Collections.Generic.Dictionary`2.get_Item(TKey key) +11759657
   Kentor.AuthServices.Configuration.IdentityProviderDictionary.get_Item(EntityId entityId) +155

[KeyNotFoundException: No Idp with entity id "http://stubidp.kentor.se/Metadata" found.]
   Kentor.AuthServices.Configuration.IdentityProviderDictionary.get_Item(EntityId entityId) +291
   Kentor.AuthServices.Saml2P.Saml2Response.CheckIfUnsolicitedIsAllowed(IOptions options) +108
   Kentor.AuthServices.Saml2P.Saml2Response.Validate(IOptions options) +37
   Kentor.AuthServices.Saml2P.<CreateClaims>d__53.MoveNext() +170
   System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +381

你能告诉我为什么 Kentor 无法获取元数据吗?

您将实体 ID 与元数据路径混淆了。元数据暴露在实体id的地址,但是如果你把元数据放在本地,你需要把它们分开。

var idp = new IdentityProvider(new EntityId("http://stubidp.kentor.se/Metadata"), spOptions)
{
  MetadataLocation = ""~/App_Data/KentorIDPMetadata.xml"
  AllowUnsolicitedAuthnResponse = true,
  // No need to add these if metadata is read.
  // Binding = Saml2BindingType.HttpRedirect,
  // SingleSignOnServiceUrl = new Uri("http://stubidp.kentor.se/")
};

另一种更简单的方法是直接从 idp 加载元数据:

var idp = new IdentityProvider(new EntityId("http://stubidp.kentor.se/Metadata"), spOptions)
{
  LoadMetadata = true,
  AllowUnsolicitedAuthnResponse = true,
};