Подтвердить что ты не робот

Кабель аутентификации OWIN и правильное использование промежуточного программного обеспечения Katana?

Недавно я начал изучать новую структуру ASP.Net Identity и связующее ПО Katana, там было удивительное количество кода и документации, но я вижу, что, похоже, много противоречивой информации, которую я Угадайте, это результат увеличения частоты обновлений кода.

Я ищу использовать WsFederation Authentication для внутренней службы ADFS 2, но способ, которым работает протокол аутентификации OWIN, меня немного смущает, и я надеюсь, что кто-то может предложить некоторую окончательную информацию.

В частности, меня интересует порядок, в котором должно быть подключено промежуточное программное обеспечение, и какие модули требуются в различных сценариях, я хотел бы избавиться от всего, что не обязательно должно быть там и в то же время убедитесь, что процесс максимально безопасен.

Например, кажется, что UseWsFederationAuthentication следует использовать в сочетании с UseCookieAuthentication, но я не уверен, что будет правильным AuthenticationType (this post предполагает, что это просто строка идентификатора, но важна ли она значительная?) или даже если нам все еще нужно использовать SetDefaultSignInAsAuthenticationType.

Я также заметил эту нить на форуме обсуждения Katana Project, где Тратчер упоминает общую ошибку, но не очень специфичен в отношении того, часть кода находится в ошибке.

Лично я теперь использую следующее (с помощью специального обработчика токена SAML для чтения строки токена в действительный XML-документ), он работает для меня, но оптимален ли он?

var appURI = ConfigurationManager.AppSettings["app:URI"];
var fedPassiveTokenEndpoint = ConfigurationManager.AppSettings["wsFederation:PassiveTokenEndpoint"];
var fedIssuerURI = ConfigurationManager.AppSettings["wsFederation:IssuerURI"];
var fedCertificateThumbprint = ConfigurationManager.AppSettings["wsFederation:CertificateThumbprint"];

var audienceRestriction = new AudienceRestriction(AudienceUriMode.Always);

audienceRestriction.AllowedAudienceUris.Add(new Uri(appURI));

var issuerRegistry = new ConfigurationBasedIssuerNameRegistry();

issuerRegistry.AddTrustedIssuer(fedCertificateThumbprint, fedIssuerURI);

app.UseCookieAuthentication(
    new CookieAuthenticationOptions
    {
        AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType // "Federation"
    }
);

app.UseWsFederationAuthentication(
    new WsFederationAuthenticationOptions
    {
        Wtrealm = appURI,
        SignOutWreply = appURI,
        Configuration = new WsFederationConfiguration
        {
            TokenEndpoint = fedPassiveTokenEndpoint
        },
        TokenValidationParameters = new TokenValidationParameters
        {
            AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
        },
        SecurityTokenHandlers = new SecurityTokenHandlerCollection
        {                        
            new SamlSecurityTokenHandlerEx
            {
                CertificateValidator = X509CertificateValidator.None,
                Configuration = new SecurityTokenHandlerConfiguration
                {
                    AudienceRestriction = audienceRestriction,
                    IssuerNameRegistry = issuerRegistry
                }
            }
        }
    }
);

Большое спасибо за все, что вы можете предложить, чтобы помочь устранить эту путаницу для меня.

4b9b3361

Ответ 1

Как сказал @Tratcher, параметр AuthenticationType используется Microsoft.Owin.Security как ключ для поиска экземпляров промежуточного программного обеспечения аутентификации.

В приведенном ниже коде будет использоваться следующий простой вспомогательный метод, требующий проверки подлинности всех запросов. На практике вы, скорее всего, используете атрибут [Authorize] для чувствительных контроллеров, но мне нужен пример, который не зависит от каких-либо фреймворков:

private static void AuthenticateAllRequests(IAppBuilder app, params string[] authenticationTypes)
{
    app.Use((context, continuation) =>
    {
        if (context.Authentication.User != null &&
            context.Authentication.User.Identity != null &&
            context.Authentication.User.Identity.IsAuthenticated)
        {
            return continuation();
        }
        else
        {
            context.Authentication.Challenge(authenticationTypes);
            return Task.Delay(0);
        }
    });
}

Вызов context.Authentication.Challenge(authenticationTypes) выдаст запрос проверки подлинности от каждого из предоставленных типов проверки подлинности. Мы просто собираемся предоставить тот, наш тип аутентификации WS-Federation.

Правильный код

Итак, вот пример "оптимальной" конфигурации запуска Owin для сайта, который просто использует WS-Federation, как вы:

public void Configuration(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
    {
        AuthenticationType = "WS-Fed Auth (Primary)",
        Wtrealm = ConfigurationManager.AppSettings["app:URI"],
        MetadataAddress = ConfigurationManager.AppSettings["wsFederation:MetadataEndpoint"]
    });

    AuthenticateAllRequests(app, "WS-Fed Auth (Primary)");

    app.UseWelcomePage();
}

Обратите внимание на использование "WS-Fed Auth (Primary)" AuthenticationType для уникальной идентификации экземпляра промежуточного ПО WS-Federation, который мы настроили. Это означает, что вы могли бы, например, использовать "WS-Fed Auth (Secondary)" с отдельным сервером WS-Federation в качестве резервной копии, если бы у вас было это требование.

Эта конфигурация сделает следующее:

  • Сначала расскажите о конвейере безопасности Owin, который по умолчанию мы хотим аутентифицировать запросы с значением CookieAuthentication AthenticationType по умолчанию. (Это просто константа в этом классе CookieAuthenticationDefaults, и это значение по умолчанию, используемое свойством CookieAuthenticationOptions.AuthenticationType.)
  • Затем зарегистрируйте экземпляр промежуточного ПО аутентификации cookie со всеми параметрами по умолчанию, поэтому он соответствует клавише AuthenticationType, который мы задали как значение по умолчанию на шаге 1.
  • Затем зарегистрируйте экземпляр промежуточного программного обеспечения аутентификации WS-Federation с параметрами, которые мы определяем в файле Web.config, и с пользовательским значением AuthenticationType, чтобы мы могли ссылаться на него позже.
  • После завершения регистрации промежуточного программного обеспечения аутентификации мы сообщаем конвейеру аутентифицировать все запросы (с помощью нашего настраиваемого вспомогательного метода, который вызывает методы Microsoft.Owin.Security для выдачи вызовов любому неавторизованному запросу).
  • Наконец, если пользователь прошел аутентификацию, покажите страницу приветствия!

Неверный код

Итак, есть несколько способов, по которым вы можете пойти не так.

Не предоставлять тип проверки по умолчанию

Чтобы экспериментировать, я попытался сделать это, и вы сразу увидите, в чем проблема:

public void Configuration(IAppBuilder app)
{
    var x = app.GetDefaultSignInAsAuthenticationType();

    app.SetDefaultSignInAsAuthenticationType(x);
}

Этот первый вызов даст вам исключение, указанное в вашем первом комментарии:

"Значение по умолчанию для SignInAsAuthenticationType не было найдено в свойствах IAppBuilder. Это может произойти, если ваше промежуточное программное обеспечение для проверки подлинности добавлено в неправильном порядке или отсутствует."

Вправо - потому что по умолчанию конвейер Microsoft.Owin.Security не предполагает ничего о промежуточном программном обеспечении, которое вы собираетесь использовать (т.е. Microsoft.Owin.Security.Cookies даже не известно, что он присутствует), поэтому он не знает, что должен быть по умолчанию.

Использование неправильного типа проверки подлинности по умолчанию

Это стоило мне много времени, потому что я действительно не знал, что я делаю:

public void Configuration(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType("WS-Fed AAD Auth");

    // ... remainder of configuration
}

Итак, это будет попытка проверить подлинность вызывающего абонента WS-Federation при каждом вызове. Это не то, что супер-дорого, это то, что промежуточное ПО WS-Federation действительно вызовет вызов по каждому запросу. Таким образом, вы никогда не сможете войти, и вы видите, что за вами пролегает много URL-адресов для входа.: P

Возможности

Итак, что здорово в том, что вся эта гибкость в конвейере заключается в том, что вы можете делать действительно классные вещи. Например, у меня есть домен с двумя различными веб-приложениями внутри него, работающими под разными подпакетами вроде: example.com/foo и example.com/bar. Вы можете использовать функцию сопоставления Owin (как в app.Map(...)), чтобы настроить совершенно другой протокол аутентификации для каждого из этих приложений. В моем случае используется WS-Federation, а другой - клиентские сертификаты. Попытка сделать это в монолитной структуре System.Web была бы ужасной.: P