Рубрики
IRIS

Укрощаем протоколы доверия – OAuth авторизация с InterSystems IRIS

Как разрешить компьютерам доверять друг другу в ваше отсутствие, сохраняя безопасность и приватность?

image

— Сухой «мартини». В большом бокале.
— Oui, monsieur. [Да, месье (фр.)]
— Секунду, еще не все. Три пальца «Гордона», один — водки, полпальца «Кины Ликлет». Хорошо взбейте в шейкере, а потом положите большую дольку лимона. Запомнили?

Ян Флеминг, «Казино Рояль», 1953 год

Часть 1. Истории про OAuth 2.0 and OpenID Connect

Универсальная и, похоже, сегодня в XXI веке всеми любимая связка открытых протоколов делегирования доступа и идентификации называется OAuth+OIDC. Лучше для массово использования пока ничего не придумали. Особенно популярны у фронтендеров, потому что гуляют поверх протоколов HTTP(S) и используют контейнер JWT (JSON Web Token). OpenID Connect использует для своей работы OAuth или, по другому говоря, OIDC является обёрткой для OAuth.

OpenID – открытый стандарт для аутентификации и создания систем цифровой идентификации не новинка для разработчиков. В этом 2019 году ему исполняется 14 лет. В нынешней третьей версии полное название OpenID Connect или короче OIDC. Популярен как в вебе и мобильной разработке, так и в корпоративных системах.

Его напарнику – открытому стандарту делегирования прав доступа OAuth исполняется 12 лет. И 9 лет с тех пор, как появился соответствующий стандарт RFC 5849. Мы будем опираться на современную версию протокола OAuth 2.0 и актуальный сейчас RFC 6749. Запомните, что OAuth 2.0 не совместим со своим предшественником OAuth 1.0.

OAuth – открытый протокол (схема, транспорт) для делегирования доступа, который позволяет предоставить третьей стороне ограниченный доступ к защищённым ресурсам пользователя без необходимости передавать ей (третьей стороне) логин и пароль RFC 6749

oauth.net – головной сайт про OAuth, который ведёт Аарон Пареки (Aaron Parecki)

oauth.com – руководство и тестовая среда по OAuth

Open ID Connect (OIDC) – открытый стандарт децентрализованных систем идентификации, предоставляющей пользователю возможность создать единую учётную запись для идентификации на множестве не связанных друг с другом интернет-ресурсов, используя услуги третьих лиц, использует сообщения OAuth и контейнер JWT для безопасного взаимодействия.
Строго говоря, OAuth – это не протокол, а набор правил (схема) для отделения и передачи операций по идентификации пользователей отдельному доверенному серверу при реализации архитектуры разграничения прав доступа в программных системах.

И, внимание, OAuth ничего не может сказать о конкретном пользователе! Ни кто он такой, ни где он сейчас находится, ни даже то, работает он за компьютером сейчас или нет. Но зато даёт возможность взаимодействовать системам без участия пользователя, используя уже выданные токены доступа. Это важный момент.

Может пригодиться:

  • с OAuth отлично совмещается применение языка описания атрибутного доступа XACML
  • также на OAuth опирается протокол User-Managed Access (UMA)

Совместное использование OAuth+OIDC+UMA позволяет реализовывать системы защищённой идентификации и управления доступом (Identity and Access Management – IdM, IAM) в разных предметных областях, например:

  • с помощью профиля персональных данных пациента HEART (Health Relationship Trust) в медицине
  • в платформах для идентификационных данных клиента CIAM (Consumer Identity and Access Management) для производственных и торговых компаний
  • персонализация цифровых сертификатов умных устройств в системах интернета вещей IoT (Internet of Things)

image
A New Venn Of Access Control For The API Economy

Самое главное – не храните персональные данные там же, где остальная система. Отделите физически аутентификацию и авторизацию. А ещё лучше – отдайте всю идентификацию лично человеку и никогда не храните у себя. Доверяйте устройству владельца.

Apple рассказала, какие персональные данные россиян хранит в России. Это ФИО, адрес, электронная почта, номер телефона. А вот Сообщения, фото и пр. люди сами доверяют облаку iCloud (которое не в России).

Часть 2. Короткая пьеса «Доверие и аутентификация»

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

Действующие лица:

  • Пользователь
  • Приложение-Клиент
  • Сервис Идентификации
  • Сервер Ресурсов

Действие происходит в браузере на компьютере Пользователя. Все персонажи давно знакомы друг с другом. Пользователь имеет личную учётную запись на Сервисе Идентификации. У Приложения-Клиента есть подписанный действующий договор с Сервисом идентификации и взаимные интерфейсы. Сервер Ресурсов доверяет Сервису Идентификации в части выдачи ключей доступа любому страждущему, кого тот сможет идентифицировать.

Пользователь (П): (запуская у себя клиентское веб-приложение) Дорогой Приложение-клиент, мне нужен «вот этот ресурс».
Приложение-клиент (К): Дорогой пользователь, предъяви сперва ключ от «этого ресурса». Без ключа доступ к «этому ресурсу» закрыт.
П: У меня нет такого ключа.
К: Тогда временно переключу тебя на сервис идентификации, с которым у нас договор на выдачу ключей к Серверу ресурсов. (переадресует П. на сервис идентификации)
Сервис идентификации (И): Дорогой пользователь, скажите, пожалуйста, кто вы такой и что за ключи вам требуются?
П: Я, Йцукен Пользователь Пользовательский, пароль такой-то, хочу получить доступ к «этому ресурсу».
И: Спасибо, товарищ Йцукен. Аутентификация пройдена успешно и ваша идентификация подтверждена. Вот вам ключ от «этого ресурса» (переадресует П. обратно на К.)
П: Клиент, я принёс тебе ключ от нужного мне «ресурса».
К: Спасибо, пользователь. Ключ правильный. Вот запрошенный тобой «ресурс».

Занавес. Играет вступительная симфония Рихарда Штрауса из фильма «Космическая одиссея 2001 года»

Часть 3. Реальный сервис авторизации

А теперь перейдём к делу. У нас на повестке три задачи: назначить действующих лиц, подготовить сцену и сыграть пьесу. И все решаем разом на платформе InterSystems IRIS. Но это не обязательно, можно собрать конструкцию из разных платформ на ваше усмотрение. Например в таком сочетании: OAuth сервер Keycloak + OAuth клиент и OAuth ресурс на IRIS. По другому говоря:

  1. Настроить и запустить в работу OAuth сервер с регистрацией на нём нашего демонстрационного клиента.
  2. Настроить демонстрационного OAuth клиента связав его с OAuth сервером и веб-ресурсами.
  3. Разработать клиентские приложения, умеющие использовать OAuth. Можно использовать Java, Python, C#, NodeJS. Далее пример кода приложения на ObjectScript.

На сайте сообщества разработчиков есть подробная инструкция Даниэля Кутака в трёх частях с примерами использования OAuth в IRIS для разных применений на основе CSP (часть 1, часть 2, часть 3). Настроек в OAuth достаточно много. Поэтому пишите себе чек-листы – это самое правильное им применение. Примеры и заготовки ниже.
Где взять готовый InterSystems IRIS на пробу? Есть как минимум два доступных всем варианта:

Получить готовый преднастроенный облачный IRIS сервер на обучающей платформе InterSystems Learning Services в разделе InterSystems Learning Labs.

Установить у себя готовый docker контейнер. Подробнее в статье – пошаговая инструкция для начинающих разработчиков Launching IRIS Using Docker или, кому больше по нраву видео, скринкаст-инструкция http://youtu.be/L77K9oAgexQ
Developing Solutions with InterSystems IRIS Using Docker and VSCode

1-1 Настраиваем сервер OAuth

Заходим в портал управления IRIS и выбираем раздел:

Администрирование системы >> Безопасность >> OAuth 2.0 >> Сервер

Далее в каждом пункте будет название строчки настройки и через двоеточие пример или пояснение, если есть необходимость.

image

Вкладка Общие параметры:
Описание: произвольно, например так «Authorization server»
Конечную точку генератора (далее КТГ) – имя узла: DNS имя вашего сервера
Поддерживаемые типы разрешений (выбрать не менее одного):
Код авторизации
Неявный
Учетные данные: ресурс, владелец, пароль
Учетные данные клиента
Конфигурация SSL/TLS: oauthserver

Вкладка Полномочия:
добавить поддерживаемые объемы: например, scope1 и scope2

Вкладка Интервалы:
Интервал ключа доступа: 3600
Интервал кода авторизации: 60
Обновить интервал ключа: 86400
Интервал прерывания сеанса: 86400
Период срока действия клиентского ключа (client secret): 0

Вкладка Настройки JWT:
Алгоритм входа: RS512
Алгоритм управления ключами: RSA-OAEP
Алгоритм шифрования содержимого: A256CBC-HS512

Вкладка Индивидуальная настройка:
Опознать класс: %OAuth2.Server.Authenticate
Проверить класс пользователя: %OAuth2.Server.Validate
Класс обслуживания сеанса: OAuth2.Server.Session
Сгенерировать класс ключа: %OAuth2.Server.JWT
Namespace индивидуальной настройки: %SYS
Роли индивидуальной настройки (выбрать не менее одной): %DB_IRISSYS и %Manager

Сохраняем.

1-2 Регистрируем клиента на сервере OAuth

image

Кнопка Описание клиентов >> кнопка Создать описание клиентов:

Вкладка Общие параметры:
Имя: CLIENT
Описание: произвольное
Тип клиента: Конфиденциальный
URL-адреса перенаправления: адрес точки возврата в наше приложения после идентификации
Поддерживаемые типы разрешений
Код авторизации: да
Неявный
Учетные данные: ресурс, владелец, пароль
Учетные данные клиента
JWT authorization
Поддерживаемые типы ответов
код
id_token
ключ id_token
токен
Тип авторизации: простой

Вкладка Учетные данные клиента: заполняется автоматически

Вкладка Информация о клиенте:
URL запуска:
Экран авторизации
Имя клиента
URL логотипа
URL домашней страницы клиента
URL политики
Условия сервисного URL

2-1 Настраиваем привязку на клиенте сервера OAuth

Администрирование системы >> Безопасность >> OAuth 2.0 >> Клиент

image

Создаём описание сервера:
Конечная точка генератора: берём из общих параметров сервера, смотри выше
Конфигурация SSL/TLS: выбираем из списка преднастроенных

Содержание остальных полей подгрузится с сервера автоматически, но можно настроить и вручную:

Сервер авторизации
Конечная точка авторизации: КТГ + /authorize
Конечная точка ключа: КТГ + /token
Конечная точка информации о пользователе: КТГ + /userinfo
Конечная точка самодиагностики ключа: КТГ + /revocation
Конечная точка аннулирования ключа: КТГ + /introspection
Настройки веб-токена JSON (JWT)
Другой источник, кроме динамической регистрации: выбираем JWKS из URL
URL: КТГ + /jwks

image

Из этого списка, например видно (scopes_supported и claims_supported), что сервер может предоставить OAuth-клиенту разные сведения о пользователе. И стоит обратить внимание, что при реализации вашего приложения, надо бы спросить у пользователя, какими данными он готов поделиться. Далее у нас в примере у нас будет запрашиваться разрешение только по scope1.

Сохраняем.

Если есть появляется ошибка с указанием на SSL, то заходим в настройки:
Администрирование системы >> Безопасность >> SSL/TSL конфигурации

2-2 Настраиваем клиента OAuth

Администрирование системы >> Безопасность >> OAuth 2.0 >> Клиент >> Конфигурация клиента >> Создать конфигурацию клиента

image

Вкладка Общие:
Имя приложения: demo client
Имя клиента: demo client
Описание: произвольно
Включен: да
Тип клиента: конфиденциально
Конфигурация SSL/TCL: oauthclient
URL перенаправления клиента: DNS имя вашего сервера
Требуемые типы разрешений
Код авторизации: да
Неявный
Учетные данные: ресурс, владелец, пароль
Учетные данные клиента
JWT authorization
Тип авторизации: простой

Вкладка Информация о клиенте:
Экран авторизации
URL логотипа
URL домашней страницы клиента
URL политики
Условия сервисного URL
Объем по умолчанию: берем из указанные ранее на сервере, например, scope1
Контактные адреса электронной почты (отделяются запятой)
Максимальный возраст по умолчанию (в секундах)

Вкладка Настройки JWT:
Настройки веб-токена JSON (JWT)
Создание настроек JWT из учетных данных X509
Алгоритмы IDToken
Signing: RS256
Encryption: A256CBC
Key: RSA-OAEP
Алгоритмы Userinfo
Алгоритмы токена доступа
Алгоритмы запроса

Вкладка Учетные данные клиента:
Ид. клиента: из выданного при регистрации клиента на сервере (смотри выше)
ID клиента выдан
Секрет клиента: из выданного при регистрации клиента на сервере (смотри выше)
Срок действия клиентского ключа (client secret) истекает
Регистрационный URI-адрес клиента

Сохраняем.

Часть 4. Код

Создадим минималистичное веб-приложение с OAuth авторизацией и REST.
При работе OAuth полагается на то, что каналы связи между участниками взаимодействия (сервером, клиентов, веб-приложением, браузером пользователя, сервером ресурсов) как-то защищены. Чаще всего эту роль играют протоколы SSL/TLS. Но работать OAuth будет и на незащищенных каналах. Так например, сервер Keycloak, по умолчанию использыет HTTP протокол и обходится без защиты. Это упрощает разработку и отладку при разработке. При реальном использовании сервисов OAuth защита каналов должна быть включена строго обязательно – это записано в документации Keycloak. Разработчики InterSystems IRIS придерживаются более строгого подхода для OAuth – использование SSL/TSL обязательно. Единственное упрощение – вы можете использовать самоподписанные сертификаты или воспользоваться встроенным в IRIS сервисом PKI (Администрирование системы >> Безопасность >> Система открытых ключей). Проверка авторизации пользователя производится с явным указанием двух параметров – зарегистрированного на OAuth сервере и в OAuth клиенте имени вашего приложения и поддерживаемого объёма (scope – интересно как его правильно назвать по русски?):

Parameter OAUTH2APPNAME = "OAuthClient";

set isAuthorized = ##class(%SYS.OAuth2.AccessToken).IsAuthorized(
        ..#OAUTH2APPNAME,
        .sessionId,
        "scope1",
        .accessToken,
        .idtoken,
        .responseProperties,
        .error)

При отсутствии авторизации, готовим ссылку на запрос идентификации пользователя и получение от него разрешение на работу с нашим приложением. Здесь нам необходимо указать не только зарегистрированного на OAuth сервере и в OAuth клиенте имя приложения и запрашиваемый объём (scope), но и обратную ссылку, в какую точку веб-приложения вернуть пользователя.

Parameter OAUTH2CLIENTREDIRECTURI = "https://52773b-76230063.labs.learning.intersystems.com/oauthclient/"

set url = ##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint(
        ..#OAUTH2APPNAME,
        "scope1",
        ..#OAUTH2CLIENTREDIRECTURI,
        .properties,
        .isAuthorized,
        .sc)

Мы используем встроенный идентификационный сервис IRIS и, соответственно, пользователей регистрируем на OAuth сервере IRIS. Для примера достаточно задать пользователю только имя и пароль, других настроек в учётной записи делать не потребуется.

При переводе пользователя по полученной ссылке, сервер проведёт процедуру опознания пользователя и запроса у него разрешений на оперированием учётными данными в веб-приложением, а также и сохранит результат у себя в глобале OAuth2.Server.Session в области %SYS:

image

image

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

set valid = ##class(%SYS.OAuth2.Validation).ValidateJWT(
   .#OAUTH2APPNAME,
   accessToken,
   "scope1",
   .aud,
   .JWTJsonObject,
   .securityParameters,
   .sc
)

Полный рабочий код примера работы с OAuth:

Class OAuthClient.REST Extends %CSP.REST
{

Parameter OAUTH2APPNAME = "OAuthClient";

Parameter OAUTH2CLIENTREDIRECTURI = "https://52773b-76230063.labs.learning.intersystems.com/oauthclient/";

// to keep sessionId
Parameter UseSession As Integer = 1;

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
    <Routes>
        <Route Method="GET" Url = "/" Call = "Do" />
    </Routes>
}

ClassMethod Do() As %Status
{
    // Check for accessToken
    set isAuthorized = ##class(%SYS.OAuth2.AccessToken).IsAuthorized(
        ..#OAUTH2APPNAME,
        .sessionId,
        "scope1",
        .accessToken,
        .idtoken,
        .responseProperties,
        .error)
 
    // to show accessToken
    if isAuthorized {
        set valid = ##class(%SYS.OAuth2.Validation).ValidateJWT(
            ..#OAUTH2APPNAME,
            accessToken,
            "scope1",
            .aud,
            .JWTJsonObject,
            .securityParameters,
            .sc
        )
        &html< Hello! >
            w "You access token = ", JWTJsonObject.%ToJSON()
        &html< </html> >
        quit $$$OK
    }

    // perform the process of user and client identification and get accessToken       
    set url = ##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint(
        ..#OAUTH2APPNAME,
        "scope1",
        ..#OAUTH2CLIENTREDIRECTURI,
        .properties,
        .isAuthorized,
        .sc)
 
    if $$$ISERR(sc) {
          w "error handling here"
          quit $$$OK
    }
    
    // url magic correction: change slashes in the query parameter to its code
    set urlBase = $PIECE(url, "?")
    set urlQuery = $PIECE(url, "?", 2)
    set urlQuery = $REPLACE(urlQuery, "/", "%2F")
    set url = urlBase _ "?" _ urlQuery
    
    &html<
        <html>
            

<h4>Авторизация в IRIS через сервис OAuth2</h4>


    
            <a href = "#(url)#">Авторизовать в <b>IRIS</b></a>
        </html>
    >

    quit $$$OK
}
}

Если необходимо, то включайте режим расширенных отладочных сообщений на OAuth сервере и OAuth клиенте. Сообщения пишутся в глобал ISCLOG в области %SYS. Наберити в терминале вашего IRIS (или установите и воспользуйтесь веб-терминалом):

set ^%ISCLOG = 5
set ^%ISCLOG("Category", "OAuth2") = 5
set ^%ISCLOG("Category", "OAuth2Server") = 5  

Подробнее в документации по IRIS Using OAuth 2.0 and OpenID Connect.

Выводы:

  1. OAuth помогает физически и территориально разнести сервисы с регистрационными данными пользователей и “рабочие” базы данных. И, тем самым, усилить защиту данных идентификации и, при необходимости, соблюсти требования законов о защите персональных данных разных стран.
  2. С использованием OAuth, пользователю можно предоставлять возможность безопасной работы одновременно с нескольких устройств и минимально “светить” его персональные данные разным сервисам и приложениям. Равно как и не брать на свои сервисы “излишней” информации о пользователях, то есть вести деперсонализированную обработку данных в своих сервисах.
  3. При применении InterSystems IRIS, у вас есть полный набор готовых инструментов по тестированию и развёртыванию сервисов OAuth и OIDC как автономно, так и в кооперации со сторонними программными продуктами.

В каких отраслях чаще всего применяется платформа InterSystems IRIS?
Для автоматизации здравоохранения, в финансовом секторе, для проектов по электронному правительству, в логистке, ритейле и во многих других отраслях.

Если вам интересны задачи автоматизации здравоохранения, то обратите внимание на стандарт FHIR. В InterSystems IRIS for Health (специальной версии платформы InterSystems IRIS) есть поддержка стандарта FHIR для интеграции и разработки приложений Как видно выше, все возможности OAuth легко доступны и полностью готовы к использованию. При необходимости, можно заменить классы-обработчики и пользовательские интерфейсы на собственные. Настройки сервера и клиента OAuth можно делать из конфигурационных файлов, взамен использования портала управления.

Оригинал статьи

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

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