Сетевой дневник одного программиста

Персональный блог Константина Огородова

При разработке бизнес-приложений часто требуется реализовать аутентификацию и авторизацию. Чтобы облегчить жизнь разработчикам на платформе .net Microsoft предлагает ASP .NET Core Identity (METANIT) — систему для авторизации и управления пользователями. Система может использоваться самостоятельно либо использовать внешние поставщики входа, такие как Facebook, Google, Microsoft, Twitter. Но это для одного приложения, а в контексте архитектуры микросервисов MS предлагает использовать IdentityServer для организации единой точки входа (SSO). Однако здесь есть 2 неприятных момента: во-первых IdentityServer это каркас, а не готовое решение, т.е. придётся потратить ещё некоторое кол-во усилий прежде чем получить работающий сервер. Во-вторых поддержка бесплатной 4-й версии IdentityServer’а заканчивается в ноябре 2022, а последняя на момент написания статьи 6-я версия требует лицензию. И хотя бесплатная лицензия Community Edition имеется, это уже не OpenSource и будет весьма неприятно, если в самый неподходящий момент придётся задуматься о приобретении лицензии. Однако я уже был готов рискнуть, потому что ребятки из Duende предлагали не только IdentityServer, но и BFF hosting library — библиотеку для аутентификации одностраничных приложений (SPA) на сервере при использовании подхода «каждому интерфейсу своя серверная часть» (BFF). Подход этот используется не только для того чтобы серверная часть обслуживала только один тип пользовательского интерфейса, но и с точки зрения безопасности, чтобы не тащить секретные ключики в клиентское приложение. Идея проста, но в то же время эффективна: клиент с сервером общаются с использованием cookie, а сервер со всеми остальными с использованием OpenId Connect или OAuth. Один из авторов IdentityServer’а Dominick Baier опубликовал статью на эту тему, но мне кажется он не был первым, кто задумался о таком решении. Bernd Hirschmann заинтересовался идеей и написал свою статью с подробностями, а также выложил код на GitHub’е, который в той или иной степени используется как в Duende BFF, так и в шаблоне Blazor.BFF.OpenIDConnect.Template, автором которого является Damien Bowden. Damien также описал как пользоваться шаблоном в связке с OpenIddict — ещё одной реализацией OIDC сервера на .net. Но прелесть шаблона от Damien в том, что он может использоваться с любым OIDC сервером. И вот тут «на сцену выходит» KeyCloak — полностью готовый к использованию сервер управления доступом с открытым исходным кодом от RedHat. Разворачивать удобнее всего конечно же готовый образ Docker в контейнер. Примечательно, что конфигурирование происходит не только за счёт переменных окружения KEYCLOAK_ADMIN, KEYCLOAK_ADMIN_PASSWORD и TZ, но и за счёт аргументов контейнера. В моём случае использовались следующие аргументы:

  • start-dev — для запуска в тестовом режиме
  • —db=mysql — тип используемой СУБД. Поддерживаются несколько.
  • —db-url-host=<IP адрес MySql сервера>
  • —db-username=<имя DB пользователя keycloak>
  • —db-password=<пароль DB пользователя keycloak>
  • —proxy=edge — режим общения KeyCloak с обратным прокси при котором не используется HTTPS, а только HTTP.
  • —health-enabled=true — <KeyCloak URL>/health
  • —metrics-enabled=true — <KeyCloak URL>/metrics

Если не указано, то по умолчанию используется база данных keycloak, в которой будут созданы все необходимые объекты при первом запуске. Дальше займёмся администрированием: во-первым необходимо создать и настроить новую область (Realm) в рамках которой будет использоваться SSO. Во-вторых — добавить клиентов с указанием типа доступа (Access Type). Для OIDC должно быть Confidential, тогда станет доступна вкладка Credentials с секретным ключиком.

Теперь что касается клиента:

services.AddOpenIdConnect(options =>
{
    options.SignInScheme = "Cookies";
    options.Authority = oidcConfig.Authority;
    options.ClientId = oidcConfig.ClientId;
    options.ClientSecret = oidcConfig.ClientSecret;
    options.RequireHttpsMetadata = true;
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.UsePkce = true;
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("offline_access");
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
});

Это фрагмент кода из шаблона Damien’а с небольшими моими изменениями для взаимодействия с KeyCloak. Обратите внимание, что Authority — это не только адрес сервера, а адрес с указанием конкретной области, т.е. <host_url>/realms/<realm_name>. В другой своей статье Damien предлагает прописать ещё и URL метаданных, но у меня завелось и без этого.

Теперь пару слов об архитектуре в целом, как она мне представляется: KeyCloak выступает в качестве единого сервера аутентификации и хранит базовые данные о пользователях. Дополнительные данные о пользователях хранятся в атрибутах. Для простых сценариев этого достаточно и управление пользователями может происходить используя UI KeyCloak. Для более сложных сценариев придётся создать отдельное приложение для управления пользователями со своим UI и бизнес-логикой. Это приложение будет «общаться» с KeyCloak используя API.

Таким вот нехитрым образом мы получаем «вагон и тележку» готового функционала от KeyCloak и невероятно быстрый запуск системы авторизации и единой точки входа, по сравнению с другими подходами, на старте разработки приложения. Красота, да и только!

KeyCloak

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Пролистать наверх