Unified Identity Management logo figure Unified Identity Management logo figure
Поиск Поиск по документации

Аутентификация по протоколу WebAuthn на основе биометрических данных

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

RooX UIDM позволяет выполнять аутентификацию пользователей с использованием современного протокола Web Authentification API (далее — WebAuthN), в том числе на основе биометрических данных — распознавания лица, отпечатка пальца и других сведений об уникальных биологических характеристиках пользователя. В соответствии с протоколом WebAuthN биометрические данные используются только на стороне клиентского устройства (аутентификатора) и по сети не передаются.

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

В основе протокола WebAuthN лежит надёжная асимметричная криптография (криптография с открытым ключом).

Создание ключей и аутентификация по протоколу WebAuthN

Создание ключей ключевой пары и регистрация открытого ключа

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

Закрытый (приватный) ключ используется пользователем для подписания направляемых им сообщений.

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

Закрытый ключ сохраняется на пользовательском устройстве в защищённом хранилище аутентификатора (программного компонента или устройства).

Открытый ключ вместе со идентификатором (логином) пользователя направляется на сервер и сохраняется на нём⁠[1].

Аутентификация

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

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

Аутентификация (доказывание владения закрытым ключом) выполняется следующим образом:

  • сервер направляет стороне, запрашивающей аутентификацию, challenge (случайное число);

  • запрашивающая аутентификацию сторона (пользователь) подписывает это число закрытым ключом из ключевой пары, созданной для аутентификации на этом ресурсе;

  • сервер, получив ответ запрашивающей стороны, проверяет его подпись при помощи хранящегося на сервере открытого ключа пользователя, которым сервер располагает после выполнения процедуры регистрации открытого ключа;

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

При аутентификации по протоколу WebAuthN может предоставляться сертификат ключевой пары, выданный третьей доверенной (удостоверяющей) стороной. Открытый ключ пользователя, направляемый на сервер, подписывается удостоверяющей стороной (закрытым ключом). Сервер, используя открытый ключ удостоверяющей стороны, проверяет подпись удостоверяющей стороны.

webauthn
Рисунок 1. Схема работы протокола Web Authentification API (WebAuthN)

Сценарии с использованием протокола WebAuthN

Регистрация устройства для аутентификации на основе биометрических данных

Предварительные требования
  • Выполнена аутентификация пользователя (в браузере сохранён токен доступа).

  • Устройство поддерживает технологию WebAuthN.

Сценарий
  1. Пользователь переходит на страницу управления способами аутентификации.

  2. Браузер отображает элемент пользовательского интерфейса (кнопку), указывающий на возможность привязать устройство.

  3. При нажатии на кнопку выполняется запрос API: Инициализация сценария привязки для получения параметров электронной подписи. Текущий токен доступа передается браузером автоматически.

  4. Сервер генерирует случайное число (nonce) и возвращает его в ответе.

  5. Клиентский код вызывает метод credentials.create().

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

  7. Браузер выполняет запрос API: Привязка нового ключа на регистрацию открытого ключа. Передаются execution, clientData, attestation.

  8. Сервер выполняет проверки clientData, attestation в соответствии со спецификацией WebAuthN.

  9. Сервер создает запись в таблице CertificateCredentials, в которой открытый ключ ассоциируется с логином пользователя.

Аутентификация на ранее зарегистрированном устройстве

Предварительные требования
Сценарий
  1. Пользователь переходит на страницу выбора способа аутентификации.

  2. Браузер отображает элемент пользовательского интерфейса (кнопку), указывающую на возможность аутентификации по протоколу WebAuthN.

  3. При нажатии выполняется запрос API: Инициализация сценария аутентификации на получение параметров подписания. Текущий токен доступа передается браузером автоматически.

  4. Сервер генерирует случайное число (nonce) и возвращает его в ответе.

  5. Клиентский код вызывает метод credentials.get().

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

  7. Браузер выполняет запрос API: Аутентификация с открытым ключом из ключевой пары на аутентификацию с использованием протокола WebAuthN. Передаются execution, credentialId, authenticatorData, clientData, userHandle, signature.

  8. Сервер выполняет проверки переданных данных в соответствии со спецификацией WebAuthN.

  9. Сервер выполняет поиск в таблице CertificateCredentials. Если открытый ключ зарегистрирован, аутентификация считается успешной.

  10. Выполняется запись события аутентификации в БД аудита.

  11. Выпускаются и возвращаются токен доступа, токен обновления доступа.

Спецификация API

Создание ключевой пары и привязка открытого ключа к идентификатору пользователя

Инициализация сценария привязки

Запрос
POST {host}/customer-webapi-1.0/webauthn/addInitiate
Content-Type: application/json
Accept: application/json

Запрос выполняется с предоставлением клиентского токена доступа. Токен может быть передан или в заголовке Authorization, или в Cookie. Имя cookie настраивается, см. Установка и настройка функциональности

Тело запроса отсутствует.

Успешный ответ
HTTP 200 OK
Пример тела ответа
{
    "continuationKey": "b409234f-25b5-4e7f-b632...",
    "approvalInfo": {
        "serverNonce": "1234",
        "rpId": "uidm.ru"
    },
    "form": { ... },
    "status": "approval_required"
}
Таблица 1. Описание параметров ответа
Переменная Описание Комментарий

continuationKey

Токен поддержания сценария

Должен передаваться на сервер при следующем обращении в рамках сценария. Является полным аналогом параметра execution из Протокола аутентификации.

approvalInfo

Атрибуты сценария для использования на стороне клиентского приложения.

Содержит различные параметры, необходимые клиентскому приложению для работы в рамках сценария. На данном шаге важны параметры rpId и serverNonce. Может содержать другие параметры. Клиенсткое приложение должно игнорировать незнакомые параметры. Аналогично параметру view из Протокола аутентификации.

form

Машинное описание формы ввода для данного шага сценария.

Аналогично атрибуту form из Протокола аутентификации, но содержит специфичные для данного сценария поля. Клиентское приложение должно анализировать параметр errors внутри form.

status

Статус ответа.

На данный момент для этого запроса всегда принимает значение approval_required

Отсутствие ошибок в form.errors означает, что можно перейти к шагу API: Привязка нового ключа.

Из ответа на запрос необходимо сохранить значение атрибута continuationKey.

Также из ответа необходимо сохранить значения полей rpId и serverNonce и передать их в качестве значений для параметров rpId и challenge методу create() WebAuthN.

Возможные ошибки

В зависимости от типа и причины ошибки, информация о ней может вернуться как в виде соответствующего HTTP Status, так и в виде значения параметра form.errors при HTTP Status=200

Таблица 2. Перечень кодов HTTP Status
Код возврата Описание Вероятные причины и поведение клиентского приложения

400

Некорректный запрос

Ошибка реализации протокола. Пользователю необходимо сообщить о невозможности выполнения операции.

401

Пользователь неавторизован

Не передан токен доступа или передан невалидный токен доступа. Необходимо инициировать повторную аутентификацию пользователя

403

Операция запрещена

Передан валидный токен, но текущие политики не позволяют выполнить данную операцию. Необходимо проверить настройку политик и выполнение их условий

500

Ошибка обработки запроса на стороне сервера

Непредвиденная ошибка на стороне сервера. Необходимо выполнить диагностику проблему по логам компонентов customer-webapi и sso-server

Таблица 3. Перечень возможных ошибок form.errors
Код ошибки Описание Вероятные причины и поведение клиентского приложения

webauthn-disabled

Поддержка webauthn выключена в настройках сервера.

Необходимо включить поддержку webauthn в настройках. Продолжение сценария невозможно.

Привязка нового ключа

Запрос
POST {host}/customer-webapi-1.0/webauthn/add
Content-Type: application/json
Accept: application/json
Тело (параметры) запроса
{
    "continuationKey": "...",
    "attestation": "...",
    "clientData": "..."
}
Таблица 4. Описание параметров запроса
Переменная Описание Комментарий

continuationKey

Токен поддержания сценария

Передается последний полученный от сервера

attestation

Base64-кодированная строка AuthenticatorAttestationResponse.attestationObject

Документация mozilla.org

clientData

Base64-кодированная строка AuthenticatorAttestationResponse.clientDataJSON

Документация mozilla.org

Успешный ответ
HTTP 200 OK
Пример тела ответа
{
   "status": "done"
}

Наличие в ответе поля status со значением done означает, что публичный ключ успешно привязан к идентификатору пользователя.

Наличие в ответе поля status со значением error означает, что при выполнении запроса произошла логическая ошибка. Формат ответа и возможные ошибки приведены ниже.

Возможные ошибки

В зависимости от типа и причины ошибки, информация о ней может вернуться как в виде соответствующего HTTP Status, так и в виде значения параметра form.errors при HTTP Status=200. В последнем случае ответ от сервера будет иметь следующий формат:

{
    "continuationKey": "b409234f-25b5-4e7f-b632...",
    "approvalInfo": {
        "serverNonce": "1234",
        "rpId": "uidm.ru"
    },
    "form": { ... },
    "status": "approval_required"
}
Таблица 5. Описание параметров ответа
Переменная Описание Комментарий

continuationKey

Токен поддержания сценария

Должен передаваться на сервер при следующем обращении в рамках сценария. Является полным аналогом параметра execution из Протокола аутентификации.

approvalInfo

Атрибуты сценария для использования на стороне клиентского приложения.

Содержит различные параметры, необходимые клиентскому приложению для работы в рамках сценария. На данном шаге важны параметры rpId и serverNonce. Может содержать другие параметры. Клиентское приложение должно игнорировать незнакомые параметры. Аналогично параметру view из Протокола аутентификации.

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

form

Машинное описание формы ввода для данного шага сценария.

Аналогично атрибуту form из Протокола аутентификации, но содержит специфичные для данного сценария поля. Клиентское приложение должно анализировать параметр errors внутри form.

status

Статус ответа.

На данный момент для этого запроса может принимать значения done при успешном выполнении операции или error при возниковении логической ошибки.

Таблица 6. Перечень кодов HTTP Status
Код возврата Описание Вероятные причины и поведение клиентского приложения

400

Некорректный запрос

Ошибка реализации протокола. Пользователю необходимо сообщить о невозможности выполнения операции.

401

Пользователь неавторизован

Не передан токен доступа или передан невалидный токен доступа. Необходимо инициировать повторную аутентификацию пользователя

403

Операция запрещена

Передан валидный токен, но текущие политики не позволяют выполнить данную операцию. Необходимо проверить настройку политик и выполнение их условий

500

Ошибка обработки запроса на стороне сервера

Непредвиденная ошибка на стороне сервера. Необходимо выполнить диагностику проблему по логам компонентов customer-webapi и sso-server

Таблица 7. Перечень возможных ошибок form.errors
Код ошибки Описание Вероятные причины и поведение клиентского приложения

validation-failed

Проверка attestation завершилась ошибкой.

Необходимо предложить пользователю повторить операцию.

credentials-exist

Предъявленный сертификат клиента уже используется для какой-то учетной записи.

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

Аутентификация на основе протокола WebAuthN

Инициализация сценария аутентификации

Запрос
POST {host}/sso/oauth2/access_token
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Тело (параметры) запроса⁠[2]
client_id=oauth_front_m2m&
client_secret=password&
realm=/customer&
grant_type=urn:roox:params:oauth:grant-type:m2m&
service=login-by-webauthn

Запрос выполняется с предоставлением клиентского токена доступа.

Таблица 8. Описание параметров запроса
Переменная Описание Комментарий

client_id

Идентификатор приложения

client_secret

Секрет приложения

Передается, если сейчас работает m2m-протокол. Если /oauth/authorize, то параметр не передается

Успешный ответ
HTTP 200 OK
Пример успешного ответа
{
    "execution": "b409234f-25b5-4e7f-b632...",
    "view": {
        "serverNonce": "1234",
        "rpId": "uidm.ru",
    },
    "form": { … },
    "step": "webauthn-assertion"
}

Наличие в ответе поля step со значением webauthn-assertion означает, что можно перейти к шагу API: Аутентификация с открытым ключом из ключевой пары.

Из ответа на запрос необходимо сохранить значение атрибута execution.

Также из ответа необходимо сохранить значения полей rpId и serverNonce и передать их в качестве значений для параметров rpId и challenge методу create() WebAuthN.

Аутентификация с открытым ключом из ключевой пары

Запрос
POST {host}/sso/oauth2/access_token
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Тело (параметры) запроса⁠[3]
client_id=oauth_front_m2m&
client_secret=password&
realm=/customer&
grant_type=urn:roox:params:oauth:grant-type:m2m&
execution=<1234>&
_eventId=next&
credentialId=<ABCD>&
authenticatorData=<ABCD>&
clientData=<ABCD>&
userHandle=<sso_1>&
signature=<ABCD>

Значения параметров execution, credentialId, authenticatorData, clientData, userHandle, signature даны условно.

Таблица 9. Описание параметров запроса
Переменная Описание Комментарий

client_id

Идентификатор приложения

client_secret

Секрет приложения

Передается, если сейчас работает m2m протокол.

Если /oauth/authorize, то параметр не передается

execution

Токен поддержания сценария

Передается последнее значение execution, полученное от сервера в ходе выполнения сценария

credentialId

Идентификатор credential.id

authenticatorData

Base64-кодированная строка AuthenticatorAssertionResponse.authenticatorData

clientData

Base64-кодированная строка AuthenticatorAssertionResponse.clientData

userHandle

UTF-8 cтрока AuthenticatorAssertionResponse.userHandle

Пример преобразования:

var decoder = new TextDecoder("utf-8");

function ab2str(buf) {
   return decoder.decode(new Uint8Array(buf));
}

Кодировка Base64 здесь не используется, поскольку это строка в кодировке UTF-8.

signature

Base64-кодированная строка AuthenticatorAssertionResponse.signature

Успешный ответ
HTTP 200 OK
Пример тела ответа
{
    "access_token": "..."
}

Наличие токена доступа (access_token) в теле ответа означает, что аутентификация выполнена успешно.

Установка и настройка функциональности

Используемые компоненты

Для работы функциональности требуется использование компонента customer-webapi. Запросы, адресованные на URL вида {host}/customer-webapi-1.0/webauthn должны перенаправляться на данный компонент

Настройки функциональности

Для работы функциональности необходимо выполнить следующие настройки:

Добавить следующие свойства для работы WebAuthN в файл с настройками:

# описание: выключатель функциональности входа по webauthn
# тип данных: boolean
# единицы измерения: нет
com.rooxteam.sso.login-by-webauthn.enabled=true

# описание: выключатель функциональности входа по webauthn для указанного {realm}
# тип данных: boolean
# единицы измерения: нет
com.rooxteam.sso.{realm}.webauthn.enabled=true

# описание: значение Relying Party Identifier согласно спецификации WebAuthn. Содержит домен сервиса UIDM
# тип данных: string
# единицы измерения: нет
# ограничения: валидный домен
com.rooxteam.sso.{realm}.webauthn.rpId={sso.public.host}

# описание: список origins, согласно спецификации WebAuthn
# тип данных: массив строк, разделенных запятой
# единицы измерения: нет
# ограничения: список валидных URL
com.rooxteam.sso.{realm}.webauthn.origins={sso.public.protocol}://{sso.public.host}

# описание: список поддерживаемых алгоритмов для публичных ключей, согласно спецификации WebAuthn
# тип данных: массив строк
# единицы измерения: нет
com.rooxteam.sso.{realm}.webauthn.pubKeyAlgs=-7,-257
Таблица 10. Описание параметров
Параметр Описание Пример

{realm}

Название реалма, для которого выполняются настройки.

customer

{sso.public.host}

Публичный домен сервиса UIDM

uidm.somedomain.com

{sso.public.protocol}

Протокол для обращения к UIDM из публичной сети.

https

Убедиться, что уже настроены и при необходимости настроить следующие общие настройки взаимодействия customer-webapi и sso-server:

# описание: Внутренний (для обращения внутри сети между компонентами) URL sso
# тип данных: url
# единицы измерения: нет
# ограничения: валидный url
com.rooxteam.aal.sso.endpoint={sso.private.url}

# описание: Имя клиента для аутентификации запросов к sso-server.
# тип данных: string
# единицы измерения: нет
# ограничения: нет
com.rooxteam.aal.auth.client={client_id}

# описание: Пароль клиента для аутентификации запросов к sso-server
# тип данных: string
# единицы измерения: нет
# ограничения: нет
com.rooxteam.aal.auth.password={client_password}

# описание: Пароль клиента с указанным именем для аутентификации обращений к sso-server.
# тип данных: string
# единицы измерения: нет
# ограничения: нет
com.rooxteam.aal.auth.client.{client_id}.password={client_password}

# описание: имя куки, в которой передается токен доступа
# тип данных: string
# единицы измерения: нет
# ограничения: валидное имя куки
com.rooxteam.aal.sso.token.cookie.name={cookie_name}
Таблица 11. Описание параметров
Параметр Описание Пример

{sso.private.url}

Внутренний домен сервиса UIDM. Может совпадать или отличаться от публичного, в зависимости от того, как устроена маршрутизация запросов внутри решения

uidm.someintra.net

{client_id}

Имя oauth2-агента, для аутентификации запросов к sso

my-application

{client_password}

Пароль (secret) oauth2-агента, для аутентификации запросов к sso

verysecretpasssword

{cookie_name}

Имя cookie, в которой передается токен доступа

at

Добавить следующие политики в настройках sso-server:

<Policy name="webauthn-add" referralPolicy="false" active="true">
   <Rule name="urlScopeRule">
       <ServiceName name="iPlanetAMWebAgentService"/>
       <ResourceName name="/webauthn/add"/>
       <AttributeValuePair>
           <Attribute name="POST"/>
           <Value>allow</Value>
       </AttributeValuePair>
   </Rule>
   <Subjects>
       <Subject name="AuthUsers" type="AuthenticatedUsers"/>
   </Subjects>
   <Conditions>
       <Condition name="authLevelCondition-customer" type="AuthLevelCondition">
           <AttributeValuePair>
               <Attribute name="AuthLevel"/>
               <Value>/customer:5</Value>
           </AttributeValuePair>
       </Condition>
   </Conditions>
</Policy>
<Policy name="certificateCredentials" referralPolicy="false" active="true">
   <Rule name="urlScopeRule">
       <ServiceName name="iPlanetAMWebAgentService"/>
       <ResourceName name="/certificateCredentials"/>
       <AttributeValuePair>
           <Attribute name="DELETE"/>
           <Value>allow</Value>
       </AttributeValuePair>
   </Rule>
   <Subjects>
       <Subject name="AuthUsers" type="AuthenticatedUsers"/>
   </Subjects>
   <Conditions>
       <Condition name="authLevelCondition-customer" type="AuthLevelCondition">
           <AttributeValuePair>
               <Attribute name="AuthLevel"/>
               <Value>/customer:0</Value>
           </AttributeValuePair>
       </Condition>
       <Condition name="multi-spelTokenCondition" type="SpelTokenCondition">
           <AttributeValuePair>
               <Attribute name="allow-if"/>
               <Value>
               (token['claims'].containsKey('roles')
               and (token['claims']['roles'].contains('ROLE_SYSTEM')))
               </Value>
           </AttributeValuePair>
           <AttributeValuePair>
               <Attribute name="denied-advice"/>
               <Value>Wrong user</Value>
           </AttributeValuePair>
       </Condition>
   </Conditions>
</Policy>
Полезные ссылки

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