Avanpost FAM/MFA+ : 3.3.2. OAuth/OpenID Connect

Avanpost FAM реализует функциональность OpenID Connect Identity Provider и предоставляет для приложений и систем набор HTTP(S)-методов в соответствии с протоколами OAuth 2.0 и OpenID Connect.

Avanpost FAM предоставляет приложениям полнофункциональную реализацию протоколов OpenID Connect 1.0 и OAuth 2.0 и включает в себя следующие возможности:

  • Аутентификация посредством всех стандартных Grant Types/OAuth 2.0 Flow:
    • Authorization Code Grant,
    • Authorization Code Grant with PKCE,
    • Refresh Token Grant,
    • Password Grant,
    • Client Credentials Grant,
    • Implicit Grant,
    • Hybrid Grant.
  • Поддержка публичных (Single-Page-приложения, мобильные приложения) и не публичных (приложения с бэкендом) клиентов с явным разделением.
  • Поддержка стандартных наборов (scopes) атрибутов (claims) OpenID Connect: openid, profile, email, phone
  • Поддержка механизма передачи авторизационных наборов атрибутов на основе членства пользователя в группе: groups, groups:name, groups:name:join, groups:by_app.
  • Поддержка расширяемых настраиваемых наборов атрибутов с возможностью:
    • Передачи значения из дополнительного атрибута профиля пользователя;
    • Передачи значения, вычисляемого на основе ECMAScript-скрипта (JavaScript-подобного) и основных и дополнительных атрибутов профиля пользователя;
    • Передачи константы.
  • CORS (Cross-Origin Resource Sharing) для Single-Page без бэкенда и мобильных приложений.
  • Формирование с Access Token в стандартном формате случайной строки либо в формате JWT.
  • Аутентификация запросов со стороны сервера приложений (Client Assertion Type) по методам client_secret_basic, client_secret_jwt и private_key_jwt.

В части аутентификации, работы с сессиями и токенами Avanpost FAM предоставляет следующие возможности:

  • 2FA/MFA с использованием различных методов аутентификации.
  • Прозрачная аутентификация посредством Single Sign-On с использованием механизма сессий.
  • Централизованное завершение сессии посредством механизма Backchannel-Logout.

В части управления и администрирования OpenID Connect в Avanpost FAM предоставляет следующие возможности для каждого OpenID Connect-приложения:

  • Настройку сроков жизни токенов всех типов (Authorization Code, Access Token, ID Token, Refresh Token) для каждого OpenID Connect-приложения.
  • Настройку client_id с возможностью использовать значение, сформированное автоматически Avanpost FAM.
  • Настройку формата Access Token в формате JWT либо случайного значения.
  • Настройку стратегии завершения сессии при выходе пользователя из приложения.
  • Настройку произвольных Scopes и Claims для каждого OpenID Connect-приложения с вычислением значения на основе JavaScript-сценария.
  • Настройку модели доступа (Resources и Scopes) для каждого OpenID Connect-приложения.
  • Настройку CORS.

Схематично аутентификация в приложение с использованием OpenID Connect Avanpost FAM выглядит следующим образом:

Сценарии использования

Некоторые возможные сценарии использования OpenID Connect-интерфейса для решения прикладных задач:

  1. 2FA/MFA и SSO/SLO для веб-приложений.
  2. 2FA/MFA и SSO/SLO для десктопных приложений.
  3. 2FA/MFA и SSO/SLO для мобильных приложений.
  4. Делегированная авторизация пользователей приложений (веб-приложений, десктопных приложений, мобильных приложений).
  5. Централизованная аутентификация для API, сервисов и микросервисов.
  6. Делегированная авторизация для API, сервисов и микросервисов.

2FA/MFA и SSO/SLO для веб-приложений

Avanpost FAM может быть использован для реализации SSO/SLO/2FA/MFA-сценариев для веб-приложений при их подключении по OpenID Connect.

Интеграция веб-приложений с Avanpost FAM выполняется посредством стандартных механизмов OpenID Connect. 

Для подключения веб-приложений рекомендуется использование Authorization Code Flow with PKCE.

2FA/MFA и SSO/SLO для десктопных приложений

Avanpost FAM может быть использован для реализации SSO/SLO/2FA/MFA-сценариев для десктопных приложений при их подключении по OpenID Connect. Для унаследованных десктопных приложений без возможности реализации OAuth/OpenID Connect и других IdP-механизмов следует рассмотреть механизм Enterprise SSO

Ниже описаны возможные варианты реализации интеграции десктопного приложения с системой Avanpost FAM.

Выбор сценария аутентификации (OAuth 2.0 Flow)

Для Native-приложений допустимо использование следующих сценариев (OAuth 2.0 Flow):

  • Authorization Code Flow;
  • Authorization Code Flow with PKCE.

Authorization Code Flow следует использовать при наличии у целевого приложения backend на сервере закрытого канала связи до token_endpoint Системы.

Authorization Code Flow with PKCE следует использовать при отсутствии у целевого приложения backend закрытого канала связи до token_endpoint Системы.

Возврат кода авторизации (OAuth 2.0 Authorization Code) из Системы в приложение

Для возврата кода авторизации (OAuth 2.0 Authorization Code) аутентифицированного Системой пользователя в десктопное приложение возможно несколько схем:

  • Отображение интерфейса аутентификации Системы в WebView внутри приложения с чтением кода из адреса запроса в WebView;
  • Отображение интерфейса аутентификации Системы в браузере с возвратом кода авторизации посредством нестандартной схемы URI приложения;
  • Отображение интерфейса аутентификации Системы в браузере с возвратом кода авторизации посредством передачи запроса к локальному веб-серверу приложения.

Выбор схемы зависит от возможностей приложения и платформы, на которой выполняется приложение.

Отображение интерфейса аутентификации Системы в WebView внутри приложения с чтением кода из адреса запроса в WebView

Для сценария требуется, чтобы приложение обладало следующими возможностями:

  • Отображение WebView внутри приложения.
  • Получение информации об адресе (URL), открытом в настоящий момент в WebView.

Если приложение считает, что требуется выполнить аутентификацию пользователя средствами Системы, то:

  1. Приложение формирует запрос к authorization_endpoint в соответствии с выбранной схемой (Authorization Code Flow либо Authorization Code Flow with PKCE) и открывает сформированный запрос в WebView внутри приложения.
  2. Система в ответ на этот запрос отображает веб-интерфейс аутентификации. Пользователь выполняет аутентификацию в Системе, используя веб-интерфейс Системы.
  3. После прохождения аутентификации Система выполняет перенаправление пользователя на адрес, содержащий заполненный HTTP Query String параметр code. Приложение считывает значение параметра code.
  4. Приложение формирует запрос, используя полученный code, к token_endpoint Системы и получает в ответ набор токенов (Access Token, ID Token, Refresh Token). Пользователь аутентифицирован.

Реализация данной схемы на стороне приложения и регистрация схемы URL для обработки приложением различается в зависимости от платформы (операционной системы), поэтому для этого следует руководствоваться документацией для разработчиков под платформу:

Отображение интерфейса аутентификации Системы в браузере с возвратом кода авторизации посредством нестандартной схемы URI приложения

Запрос к authorization_endpoint Avanpost FAM для данного сценария должен содержать параметр response_mode со значением link. Данный response_mode не является стандартным с точки зрения протокола OAuth 2.0.

Для сценария требуется, чтобы приложение и платформа (операционная система на устройстве пользователя) обладали следующими возможностями:

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

Если приложение считает, что требуется выполнить аутентификацию пользователя средствами Системы, то:

  1. Приложение формирует запрос к authorization_endpoint в соответствии с выбранной схемой (Authorization Code Flow либо Authorization Code Flow with PKCE), с той лишь разницей, что в запросе должен быть передан параметр response_mode, содержащий значение link. Приложение открывает сформированный запрос в браузере пользователя по умолчанию.
  2. Система в ответ на этот запрос отображает веб-интерфейс аутентификации. Пользователь выполняет аутентификацию в Системе, используя веб-интерфейс Системы.
  3. После прохождения аутентификации Система отображает в браузере страницу Системы, содержащую ссылку с нестандартной схемой URL приложения и значение code. После подтверждения пользователем запроса на открытие ссылки браузер через вызов к платформе (операционной системе) запускает приложение с указанным URL. Приложение считывает значение параметра code.
  4. Приложение формирует запрос, используя полученный code, к token_endpoint Системы и получает в ответ набор токенов (Access Token, ID Token, Refresh Token). Пользователь аутентифицирован.
Отображение интерфейса аутентификации Системы в браузере с возвратом кода авторизации посредством передачи запроса к локальному веб-серверу приложения

Для реализации сценария требуется, чтобы приложение и платформа (операционная система на устройстве пользователя) обладали следующими возможностями:

  • Запуск приложением локального веб-сервера, принимающего HTTP-запросы.

Если приложение считает, что требуется выполнить аутентификацию пользователя средствами Системы, то:

  1. Приложение формирует запрос к authorization_endpoint в соответствии с выбранной схемой (Authorization Code Flow либо Authorization Code Flow with PKCE). Приложение открывает сформированный запрос в браузере пользователя по умолчанию.
  2. Система в ответ на этот запрос отображает веб-интерфейс аутентификации. Пользователь выполняет аутентификацию в Системе, используя веб-интерфейс Системы.
  3. После прохождения аутентификации Система перенаправляет пользователя на адрес локального веб-сервера с передачей в запросе значения параметра code
  4. Приложение формирует запрос, используя полученный code, к token_endpoint Системы и получает в ответ набор токенов (Access Token, ID Token, Refresh Token). Пользователь аутентифицирован.

2FA/MFA и SSO/SLO для мобильных приложений

Avanpost FAM может быть использован для реализации SSO/SLO/2FA/MFA-сценариев для мобильных приложений при их подключении по OpenID Connect.

Интеграция мобильных приложений с Avanpost FAM выполняется посредством стандартных механизмов OpenID Connect. 

Делегированная авторизация пользователей приложений (веб-приложений, десктопных приложений, мобильных приложений)

Avanpost FAM может быть использован для реализации сценариев делегированной авторизации для различных приложений при их подключении по OpenID Connect в рамках стандарта OAuth User-Managed Access (UMA) 2.0.

Централизованная аутентификация для API, сервисов и микросервисов

Avanpost FAM может быть использован для реализации сценариев кросс-аутентификации для API, сервисов и микросервисов при их подключении по OpenID Connect.

Делегированная авторизация для API, сервисов и микросервисов

Avanpost FAM может быть использован для реализации сценариев делегированной авторизации в рамках функциональности кросс-аутентификации для API, сервисов и микросервисов при их подключении по OpenID Connect  в рамках стандарта OAuth User-Managed Access (UMA) 2.0.

Методика интеграции

Общая методика интеграции будет описана позднее.

Диагностика ошибок

Доступные методы диагностики ошибок:

  1. Анализ журнала событий безопасности.
  2. Анализ сообщений в процессе аутентификации
  3. Анализ системного журнала на сервере службы.

Анализ журнала событий безопасности

В административной консоли доступен отдельный тип событий «OpenID Connect», который позволяет проанализировать входящие от приложений запросы.

Анализ сообщений в процессе аутентификации

OAuth 2.0 и OpenID Connect предоставляют наборы отладочных сообщений об ошибке в процессе аутентификации. В случае тестирования сценария аутентификации через браузер при наличии ошибок система предоставляет сообщение об ошибке error и подсказку error_hint, которых как правило достаточно для анализа проблем.

Анализ системного журнала на сервере службы

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

Приложение А. Endpoint'ы OpenID Connect

Доступные в Avanpost FAM в OpenID Connect Identity Provider методы:

EndpointURI PathНазначение
Discovery Endpoint


https://${baseUrl}/.well-known/oauth-authorization-serverDiscovery-запрос метаинформации о параметрах сервера авторизации в соответствии со спецификацией OAuth 2.0

https://${baseUrl}/.well-known/openid-configuration

Discovery-запрос метаинформации о параметрах сервера аутентификации в соответствии со спецификацией OpenID Connect
Public Key Endpointhttps://${baseUrl}/oauth2/public_keysПолучение перечня открытых ключей в формате JSON Web Key Set, с использованием которых должна выполняться проверка подписи токенов
Authorization Endpointhttps://${baseUrl}/oauth2/authorizeВыполнение аутентификации и авторизации с применением одного из доступных OAuth-сценариев (OAuth 2.0 Flow)
Token Endpointhttps://${baseUrl}/oauth2/tokenВыпуск и перевыпуск токенов после выполнения аутентификации и авторизации
Token Introspection Endpointhttps://${baseUrl}/oauth2/token/introspectЗапрос сведений об актуальности токенов
Token Revocation Endpointhttps://${baseUrl}/oauth2/token/revokeЗапрос на отзыв токенов, инициируемый приложением
Userinfo Endpointhttps://${baseUrl}/oauth2/userinfoПолучение расширенной информации о пользователе
End Session Endpointhttps://${baseUrl}/oauth2/end_sessionЗавершение сессии, инициируемое приложением 

Приложение Б. Структура OpenID Connect-токенов

Токены, используемые приложениями в рамках взаимодействий по OAuth и OpenID Connect, имеют различное предназначение и обладают некоторыми особенностями. Сравнение используемых токенов в Avanpost FAM приведено в таблице:

Критерий

Access Token

ID Token

Refresh Token

НазначениеПредоставление полномочий пользователяИдентификация и предоставление сведений о пользователеПеревыпуск токенов
СтруктураJWT с дополнительными атрибутами либо случайная строка (в зависимости от значения параметра «Access token type» конкретного приложения)JWT с дополнительными атрибутамиСлучайная строка
Срок жизни токенаЗависит от значения параметра «Access token lifetime (in seconds)» конкретного приложения (client_id); по умолчанию 3600 с.Зависит от значения параметра «I» конкретного приложения (client_id); по умолчанию 3600 с.Зависит от значения параметра «Refresh token lifetime (in seconds)» конкретного приложения (client_id); по умолчанию 7200 с.
Получение стандартных OAuth/OpenID Connect ClaimsДа, только REQUIRED в соответствии с RFCДаНет
Получение дополнительных ClaimsДа, в случае использования в приложении формата JWTДаНет
Получение прав доступа пользователяДаДаНет
Валидация токенаДа, подписьДа, подписьНет

Access Token

Данный вид токенов используется в соответствии со спецификацией OAuth для подтверждения авторизации пользователя. Токены, выпускаемые Системой, описаны в формате JWT и содержат в себе только минимальный набор обязательных атрибутов в соответствии со стандартом JWT, которые могут потребоваться приложению. Дополнительные scopes и claims в состав Access Token не включаются, в отличие от ID Token.

Access Token представляет из себя JWT в формате Base64 URL encoded-строки либо случайную строку. В формате JWT Access Token включает в себя, заголовок (header), содержимое (payload) и подпись.

Пример заголовка HTTP-ответа:

{
  "alg": "RS256",
  "kid": "15js14w0djw388w"
}

Пример содержимого HTTP-ответа:

{
	"aud": "application",
	"client_id": "application",
	"exp": 1609249840,
	"iat": 1609246240,
	"iss": "idp.demo.avanpost.ru",
	"sid": "1a052aa6-a014-422e-8010-6d525018d488",
	"sub": "7c74be14-883c-4e62-80a7-737e10a57280",
	"uid": "7c74be14-883c-4e62-80a7-737e10a57280"
}

Набор атрибутов, доступных в JWT, их назначение и способы получения описаны в таблице.

Срок жизни Access Token зависит от значения параметра «Access token lifetime (in seconds)» конкретного приложения (client_id).

Максимальный срок жизни выпущенного токена содержится в атрибуте exp JWT Access Token и может быть использован для контроля его актуальности на стороне приложения.

ID Token

ID Token представляет из себя JWT в формате Base64 URL encoded-строки. Включает в себя, заголовок (header), содержимое (payload) и подпись.

Пример заголовка HTTP-ответа (HTTP Header):

{
  "alg": "RS256",
  "kid": "15js14w0djw388w"
}

Пример содержимого HTTP-ответа (HTTP Payload):

{
	"iss": "demo.avanpost.ru",
	"sub": "7c74be14-883c-4e62-80a7-737e10a57280",
	"aud": "arm",
	"exp": 1609249840,
	"iat": 1609246240,
	"email": "user@testmail.ru",
	"email_verified": true,
	"sid": "1a052aa6-a0b4-422e-8010-6d525018d478",
	"at_hash": "WjybnLKINSmFjJ0ppbvhmg",
	"uid": "7c74be49-ba3c-4e62-80a7-737e10a57280"
}

Набор атрибутов, доступных в JWT, их назначение и способы получения описаны в таблице.

Срок жизни ID Token зависит от значения параметра «ID token lifetime (in seconds)» конкретного приложения (client_id).

Refresh token

Срок жизни Refresh Token зависит от значения параметра «Refresh token lifetime (in seconds)» конкретного приложения (client_id).

Набор атрибутов в JWT

Стандартные атрибуты, передаваемые в составе JWT, имеют следующую структуру:

ПараметрScope для Access TokenScope для ID TokenОписаниеТип значения
issпустоopenid

Хост, настроенный в параметре issuer файла config.json

String
expпустоopenid

UTC timestamp, когда истечения срока действия Access Token

UTC Timestamp Integer
audпустоopenid

client_id приложения/приложений либо других идентификаторов, настроенных в параметре «Audience» конкретного приложения

String
subпустоopenid

Идентификатор пользователя

UUID String
iatпустоopenidUTC timestamp, когда JWT Access Token был выпущенUTC Timestamp Integer
sidпустоopenidИдентификатор сессии в БД СистемыUUID String
jtiпусто-Идентификатор токенаUUID String
scopeпусто-Набор утверждений, который был запрошен для выдачи Access Token в составе запроса к Authorization EndpointString
expires_inпусто-Срок истечения информации, представленной в Access Token, в секундахInteger
at_hash-openidХеш Access Token, выпущенного совместно с ID Token (для дополнительной привязки ID Token к Access Token и валидации)Hash String
nameпустоopenidПолное ФИО пользователя, сформированное путём конкатенации с разделителем « »String
client_idпустоopenidИдентификатор приложения (client_id), настроенный для приложения, либо синоним (ID Synonym)String
uiduidopenid uidИдентификатор пользователяUUID String
permissionspermissionsopenid permissions

Структура с правами доступа пользователя в рамках данного приложения

Permission Array
groupsgroups

openid groups или groups:name или openid groups:name:join или openid groups:by_app

Структура с перечнем групп, в которых состоит пользователь, в рамках Системы; поддерживает несколько форматов предоставления результата, выбор формата зависит от переданного scope

Groups Array или Groups Name Array или Groups Name Join String или Groups Name By Apps

family_nameprofileopenid profileФамилияString
given_nameprofileopenid profileИмяString
localeprofileopenid profileБуквенный код предпочитаемого языка (локали) пользователя (ru, en и т.д.)String
preferred_usernameprofileopenid profileПредпочитаемый логин пользователяString
updated_atprofileopenid profileМетка последнего изменения данных профиляUTC Timestamp Integer
emailemailopenid emailАдрес электронной почтыEmail String
email_verifiedemailopenid emailПризнак подтверждённого адреса электронной почты Boolean String
phonephoneopenid phoneНомер телефонаPhone String
phone_verifiedphoneopenid phoneПризнак подтверждённого номера телефона Boolean String
Структура значений атрибута с информацией о правах пользователя (permissions)

Массив прав доступа возвращается при использовании механизма авторизации Системы и возвращается только в том случае, если пользователь авторизован и если у пользователя имеются какие-либо полномочия в составе приложения. Если у пользователя нет прав в контексте данного приложения, то claim permissions возвращён не будет.

Массив прав доступа будет возвращён в составе Access Token или ID Token только в том случае, если в запросе содержится scope permissions.

Пример permissions в составе Access Token, выпущенного Системой:

...,
"permissions": [{
    "resource_id": "avanpostfam-permission",
    "resource_scopes": [
        "view",
        "print",
        "edit"
    ]
}],
...

В данном примере в составе permissions содержатся:

  • параметр resource_set_id содержит идентификатор объекта доступа, на которые пользователю выдано разрешение;
  • массив scopes содержит набор идентификаторов операций с указанным объектом доступа, на выполнение которых пользователю выдано разрешение.
Структура значений атрибута с информацией о группах пользователя (groups)

Если в атрибуте scope содержится значение groups, то в claim groups в составе JWT будет возвращён полный JSON-массив групп, содержащий UUID-идентификатор группы (id), её наименование (name) и описание (description):

...
"groups": [
    {
      "id": "edf997b2-0140-4c30-9011-9f80dc787211",
      "name": "adminconsole"
    },
    {
      "id": "4e1caffc-97b7-4b22-88a0-578bd997cc34",
      "name": "fam-arm",
      "description": "Группа доступа АРМ"
    },
    {
      "id": "2cdd9d54-1d6e-40c6-9ab2-70a070437e76",
      "name": "fam-app1",
      "description": "Группа доступа для Приложения 1"
    }
],
...

Если в атрибуте scope содержится значение groups:name, то в составе JWT будет возвращён сокращённый JSON-массив групп, содержащий только наименования групп:

...,
"groups": [
    "adminconsole",
    "fam-arm",
    "fam-app1"
],
...

Если в атрибуте scope содержится значение groups:name:join, то в составе JWT будет возвращена строка, выполненная путём конкатенации имён групп символом-разделителем «,»:

...
"groups": "adminconsole,arm,app1",
...

Если в атрибуте scope содержится значение groups:by_app, то в составе JWT будет возвращена строка, содержащая только группы приложения:

...
"groups": "adminconsolegbroup1,adminconsolegroup2",
...

Перечень ключей для вычисления значений claim'а с типом «Вычисляемое значение»

При выборе типа значения для claim «Вычисляемое значение» можно использовать следующий перечень стандартных ключей:

АтрибутОбращение в кодеСодержащееся значение
iduser.idВнутренний UUID-идентификатор пользователя
userNameuser.userNameЛогин пользователя
familyNameuser.familyNameФамилия
givenNameuser.givenNameИмя
middleNameuser.middleNameОтчество
emailuser.emailАдрес E-mail
emailVerifieduser.emailVerifiedПризнак того, что E-mail подтверждён
localeuser.localeЛокаль пользователя
phoneNumberuser.phoneNumberНомер телефона
phoneNumberVerifieduser.phoneNumberVerifiedПризнак того, что номер телефона подтверждён
updatedAtuser.updatedAtМетка времени (timestamp) последнего обновления записи пользователя
domainuser.domainДомен пользователя
isLockeduser.isLockedБлокировка пользователя

Для обращения к значению дополнительного атрибута следует использовать обращение через ключ user.extra., добавляя наименование дополнительного атрибута. К примеру, для обращения к значению дополнительного атрибута snils следует использовать ключ user.extra.snils.

Обсуждение