Статьи

Понимание конвейера внешней аутентификации Owin

Owin облегчает внедрение нового промежуточного программного обеспечения в конвейер обработки. Это можно использовать для ввода точек останова в конвейер, для проверки состояния контекста Оуина во время аутентификации.

При создании нового проекта MVC 5.1 в проект  Startup.Auth.cs добавляется файл, который настраивает конвейер Owin с промежуточным программным обеспечением для аутентификации. С помощью двух промежуточных программ для аутентификации включаются звонки на  app.UseCookieAuthentication() и  app.UseExternalSignInCookie. Также есть закомментированные разделы для аутентификации Microsoft, Twitter, Facebook и Google. В этом посте будет использоваться Google Authentication в качестве примера, а также добавлено несколько «фиктивных» промежуточных программ, которые позволяют устанавливать точки останова и проверять конвейер аутентификации.

Вставка промежуточного программного обеспечения точки останова

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

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

app.Use(async (context, next) =>
{
  await next.Invoke();
});

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

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

    app.Use(async (Context, next) =>
        {
            await next.Invoke();
        });

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        {
            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
        }
    });

    app.Use(async (Context, next) =>
    {
        await next.Invoke();
    });

    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    app.Use(async (Context, next) =>
    {
        await next.Invoke();
    });

    app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
    {
        ClientId = "ABC.apps.googleusercontent.com",
        ClientSecret = "XYZ"
    });

    app.Use(async (Context, next) =>
    {
        await next.Invoke();
    });
}

Добавление точек останова позволяет проверять каждый шаг в конвейере. Вот как это выглядит, когда я только что нажал кнопку «Google» на странице входа в приложение.
2014-06-17 15_54_12-IdentityTest (отладка) - Microsoft Visual Studio
Перерыв наступает сразу после   вызова ExternalLogin действия над MVC  AccountController. Мы  после  звонка  next.Invoke(), но перед возвращением из этого последнего «промежуточного программного обеспечения» в цепочке. ExternalLogin Действие возвращается обычай  ChallengeResult (также найти в  AccountController.csфайле) , что при выполнении вызовов context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);. Именно этот метод устанавливает  AuthenticationResponseChallenge показанное на картинке выше.

Это важный принцип аутентификации Owin.

Компоненты не вызывают друг друга напрямую. Они помещают сообщение в AuthenticationManager контекст Owin, который проверяется другим промежуточным программным обеспечением в конвейере.

Перенаправление в Google

Код состояния ответа теперь 401 и  AuthenticationResponseChallenge установлен на AuthenticationManager. Помните, что каждое промежуточное ПО Owin может проверять каждый запрос дважды; до и после  вызова следующего промежуточного программного обеспечения в цепочке.

Когда промежуточное ПО аутентификации Google проверяет исходящий ответ и обнаруживает, что код состояния — 401, оно проверяет наличие  AuthenticationResponseChallenge типа «Google». В этом случае он найдет его и соответствующим образом изменит ответ. При достижении точки останова в строке 33, так выглядит ответ.
2014-06-17 16_21_09-IdentityTest (отладка) - Microsoft Visual Studio
Промежуточное ПО аутентификации Google изменило исходящий ответ и стало перенаправлением на службу Google oauth.

Получение возвращаемого значения от Google

Google выполняет аутентификацию и перенаправляет пользователя обратно с информацией аутентификации в строке запроса. Шагая по коду, точки останова в строках 42 и 44 никогда не будут достигнуты. Промежуточное ПО аутентификации Google обнаружило, что оно может обработать сам запрос, и никогда не вызывало следующее промежуточное ПО в конвейере. Вместо этого точка останова в строке 33 показывает, что она изменила ответ на перенаправление 302 и установила значение AuthenticationResponseGrant на  AuthenticationManager.
2014-06-17 16_37_17-IdentityTest (отладка) - Microsoft Visual Studio
Грант имеет  AuthenticationType в  ExternalCookie , что и следующий промежуточный слой в трубопроводе ищет.

Установка внешнего куки

Промежуточное программное обеспечение для проверки подлинности с помощью внешних cookie-файлов установит cookie-файл с полученным идентификатором. Файл cookie зашифрован и работает почти так же, как и файл cookie старой формы, за исключением того, что он не автоматически читается и не используется приложением.
2014-06-17 16_42_31-IdentityTest (отладка) - Microsoft Visual Studio
Внешний cookie-файл используется для запоминания идентификатора, полученного от Google во время перенаправления назад к AccountController.ExternalLoginCallback() действию.

Преобразование в локальную идентичность

Идентификационная информация, полученная от Google, является  внешней идентификацией . ASP.NET Identity строится вокруг концепции локальной идентичности,  которая может иметь ноль или более внешних имен входа. Когда контроллер MVC получает внешнюю идентификацию (посредством вызова  AuthenticationManager.GetExternalLoginInfoAsync()), он ищет локальный идентификатор в ASP.NET Identity и выдает  AuthenticationResponseGrant тип ApplicationCookie. Это итоговый ответ при проверке в строке 44.
2014-06-17 16_53_06-IdentityTest (отладка) - Microsoft Visual Studio
Теперь есть как  AuthenticationResponseGrant тип, так  ApplicationCookie и AuthenticationResponseRevoke тип,  ExternalCookie чтобы избавиться от временного внешнего cookie.

Окончательный файл cookie приложения

Наконец, поставив точку останова в строке 9, можно проверить набор файлов cookie.
2014-06-17 16_57_14-IdentityTest (отладка) - Microsoft Visual Studio
Внешний файл cookie удаляется, и файл cookie приложения устанавливается. Промежуточное программное обеспечение cookie приложения теперь будет находить cookie приложения при каждом запросе и расшифровывать его, десериализировать идентификацию содержащихся утверждений и устанавливать в запросе.

Комментарии

Благодаря использованию сообщений на  AuthenticationManager конвейере аутентификации чрезвычайно разобщены. Нет (почти) жестких зависимостей между различным промежуточным программным обеспечением или контроллером MVC от реального промежуточного программного обеспечения, которое выполняет аутентификацию. Насколько я могу судить,  AuthenticationManager и хранящиеся в нем сообщения не являются частью спецификации Owin, они являются частью реализации Owin в Microsoft Katana. Поэтому, если вы используете другую реализацию, не ожидайте, что что-то в этом посте будет верным для этой реализации.

Дизайн с отдельным внешним cookie-файлом позволяет добавить слой перевода и не использовать внешнюю идентификацию как таковую. Я думаю, что также возможно использовать внешнюю идентификацию напрямую — использование  ExternalCookie промежуточного программного обеспечения не является жестко запрограммированным в промежуточном программном обеспечении аутентификации. Промежуточное программное обеспечение ищет используемое промежуточное программное обеспечение для файлов cookie, и его можно напрямую установить в файл cookie приложения (если вы попытались, оставьте комментарий, чтобы сообщить мне!).

Гибкая архитектура всегда идет с каким-то наказанием. В этом случае настройка внешнего cookie требует дополнительного перенаправления, добавляя к числу перенаправлений, возникающих при нажатии кнопки входа в систему. Всего это три перенаправления без какой-либо реальной обратной связи с пользователем, что может раздражать соединения с высокой задержкой.

Подводя итог, я думаю, что дизайн хорош и легко настраивается с использованием различных промежуточных программ в разных комбинациях. Для написания  собственного промежуточного программного обеспечения  (о котором пойдет речь в моем следующем посте) есть еще несколько движущихся частей, которые нужно отслеживать.