Настройка Windows Identity Foundation из кода - PullRequest
2 голосов
/ 06 февраля 2011

Я экспериментирую с "WIF без конфигурации", где я хочу принять токен SAML2, сгенерированный Windows Azure AppFabric STS.

Что я делаю, это анализ текущего запроса наинформация о токене, например:

        if (Request.Form.Get(WSFederationConstants.Parameters.Result) != null)
        {
            SignInResponseMessage message = 
                WSFederationMessage.CreateFromFormPost(System.Web.HttpContext.Current.Request) as SignInResponseMessage;

            var securityTokenHandlers = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();                    

            XmlTextReader xmlReader = new XmlTextReader(
                new StringReader(message.Result));

            SecurityToken token = securityTokenHandlers.ReadToken(xmlReader);

            if (token != null)
            {
                ClaimsIdentityCollection claims = securityTokenHandlers.ValidateToken(token);
                IPrincipal principal = new ClaimsPrincipal(claims);
            }
        }

Приведенный выше код использует SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection ();сбор для проверки и обработки токена SAML.Однако: это не работает, потому что, очевидно, приложение неправильно сконфигурировано.Как мне указать следующую конфигурацию из XML программно в моей коллекции securityTokenHandlers?

  <microsoft.identityModel>
<service>
  <audienceUris>
    <add value="http://www.someapp.net/" />
  </audienceUris>
  <federatedAuthentication>
    <wsFederation passiveRedirectEnabled="true" issuer="https://rd-test.accesscontrol.appfabriclabs.com/v2/wsfederation" realm="http://www.thisapp.net" requireHttps="false" />
    <cookieHandler requireSsl="false" />
  </federatedAuthentication>
  <applicationService>
    <claimTypeRequired>
      <claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" optional="true" />
      <claimType type="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" optional="true" />
    </claimTypeRequired>
  </applicationService>
  <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
    <trustedIssuers>
      <add thumbprint="XYZ123" name="https://somenamespace.accesscontrol.appfabriclabs.com/" />
    </trustedIssuers>
  </issuerNameRegistry>
</service>

Ответы [ 3 ]

3 голосов
/ 01 сентября 2016

Я боролся с тем же и нашел рабочее решение в WIF 3.5 / 4.0. Поскольку ссылка Мартенбы кажется мёртвой, я хотел опубликовать свое решение здесь.

Наши требования были:

  • Конфигурация полностью в коде (так как мы поставляем web.config по умолчанию с приложением)
  • Максимально допустимая версия .Net 4.0 (следовательно, я использую WIF 3.5 / 4.0)

Что я использовал, чтобы прийти к решению:

  • Информация о динамической конфигурации WIF предоставлена ​​Daniel Wu здесь .
  • Это Метод для регистрации модулей HTTP во время выполнения, объяснил Дэвид Эббо. я также попробовал более элегантный метод объяснил Рик Стрэхл , но это, к сожалению, не помогло мне.

Редактировать 2016/09/02: вместо добавления отдельного «предварительного запуска приложения» code "class, как в примере Дэвида Эббо, HTTP-модули, связанные с WIF также может быть зарегистрирован в статическом конструкторе Класс HttpApplication. Я немного адаптировал код к этому Чистое решение.

Моему решению не нужно ничего в web.config. Основная часть кода находится в global.asax.cs. Конфигурация жестко запрограммирована в этом примере:

using System;
using System.IdentityModel.Selectors;
using System.Security.Cryptography.X509Certificates;
using System.Web;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Web;

namespace TestADFS
{
  public class SessionAuthenticationModule : Microsoft.IdentityModel.Web.SessionAuthenticationModule
  {
    protected override void InitializePropertiesFromConfiguration(string serviceName)
    {
    }
  }
  public class WSFederationAuthenticationModule : Microsoft.IdentityModel.Web.WSFederationAuthenticationModule
  {
    protected override void InitializePropertiesFromConfiguration(string serviceName)
    {
      ServiceConfiguration = FederatedAuthentication.ServiceConfiguration;
      PassiveRedirectEnabled = true;
      RequireHttps = true;
      Issuer = "https://nl-joinadfstest.joinadfstest.local/adfs/ls/";
      Realm = "https://67px95j.decos.com/testadfs";
    }
  }

  public class Global : HttpApplication
  {
    static Global()
    {
      Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(SessionAuthenticationModule));
      Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(WSFederationAuthenticationModule));
    }

    protected void Application_Start(object sender, EventArgs e)
    {
      FederatedAuthentication.ServiceConfigurationCreated += FederatedAuthentication_ServiceConfigurationCreated;
    }

    internal void FederatedAuthentication_ServiceConfigurationCreated(object sender, Microsoft.IdentityModel.Web.Configuration.ServiceConfigurationCreatedEventArgs e)
    {
      X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
      store.Open(OpenFlags.ReadOnly);
      X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindByThumbprint, "245537E9BB2C086D3C880982FA86267FBD66B9A3", false);
      if (coll.Count > 0)
        e.ServiceConfiguration.ServiceCertificate = coll[0];
      store.Close();
      AudienceRestriction ar = new AudienceRestriction(AudienceUriMode.Always);
      ar.AllowedAudienceUris.Add(new Uri("https://67px95j.decos.com/testadfs"));
      e.ServiceConfiguration.AudienceRestriction = ar;
      ConfigurationBasedIssuerNameRegistry inr = new ConfigurationBasedIssuerNameRegistry();
      inr.AddTrustedIssuer("6C9B96D90257B65B6F181C2478D869473DC359EA", "http://NL-JOINADFSTEST.joinadfstest.local/adfs/services/trust");
      e.ServiceConfiguration.IssuerNameRegistry = inr;
      e.ServiceConfiguration.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
      FederatedAuthentication.WSFederationAuthenticationModule.ServiceConfiguration = FederatedAuthentication.ServiceConfiguration;
    }
  }
}

Использование

Мое приложение - asp.net WebForms, работает в классическом конвейерном режиме и поддерживает аутентификацию форм, а также вход в ADFS. По этой причине проверка подлинности выполняется в общем базовом классе, который используется всеми страницами ASPX:

    protected override void OnInit(EventArgs e)
    {
      if (NeedsAuthentication && !User.Identity.IsAuthenticated)
      {
        SignInRequestMessage sirm = new SignInRequestMessage(
          new Uri("https://nl-joinadfstest.joinadfstest.local/adfs/ls/"),
          ApplicationRootUrl)
        {
          Context = ApplicationRootUrl,
          HomeRealm = ApplicationRootUrl
        };
        Response.Redirect(sirm.WriteQueryString());
      }
      base.OnInit(e);
    }

В этом коде ApplicationRootUrl - это путь к приложению, оканчивающийся на "/" ("/" важен в классическом конвейерном режиме).

Поскольку стабильная реализация для выхода из системы в смешанном режиме была не так проста, я хочу показать и код для этого. Технически это работает, но у меня все еще есть проблема с IE, сразу после входа в систему после выхода из учетной записи ADFS:

      if (User.Identity.IsAuthenticated)
      {
        if (User.Identity.AuthenticationType == "Forms")
        {
          FormsAuthentication.SignOut();
          Session.Clear();
          Session.Abandon();
          ResetCookie(FormsAuthentication.FormsCookieName);
          ResetCookie("ASP.NET_SessionId");
          Response.Redirect(ApplicationRootUrl + "Default.aspx");
          HttpContext.Current.ApplicationInstance.CompleteRequest();
        }
        else
        {
          FederatedAuthentication.SessionAuthenticationModule.SignOut();
          FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
          Uri uri = new Uri(ApplicationRootUrl + "Default.aspx");
          WSFederationAuthenticationModule.FederatedSignOut(
            new Uri("https://nl-joinadfstest.joinadfstest.local/adfs/ls/"),
            uri); // 1st url is single logout service binding from adfs metadata
        }
      }

(ResetCookie - вспомогательная функция, которая очищает куки-файл ответа и устанавливает срок его действия в прошлом)

0 голосов
/ 17 февраля 2011

К вашему сведению: найдено решение и реализовано в модуле, описанном (и связанном) здесь: http://blog.maartenballiauw.be/post/2011/02/14/Authenticate-Orchard-users-with-AppFabric-Access-Control-Service.aspx

0 голосов
/ 07 февраля 2011

Просто мысль, не знаю, работает ли это: нет ли способа получить фактический XML (который в вашем случае пуст) и изменить его во время выполнения с помощью классов в Microsoft.IdentityModel.Configuration?

В качестве альтернативы, некоторые вещи в XML, которые можно изменить во время отправки запроса на вход, в событии RedirectingToIdentityProvider , изменив SignInRequestMessage

...