Аутентификация по протоколу WebAuthn на основе биометрических данных
К настоящему времени некоторые мобильные приложения удалены из каталогов приложений. В связи с этим необходимо обеспечить пользователям взаимодействие с веб-страницами сервисов, сопоставимое по удобству с использованием приложений для мобильных устройств.
UIDM позволяет выполнять аутентификацию пользователей с использованием современного протокола Web Authentification API (далее — WebAuthN), в том числе на основе биометрических данных — распознавания лица, отпечатка пальца и других сведений об уникальных биологических характеристиках пользователя. В соответствии с протоколом WebAuthN биометрические данные используются только на стороне клиентского устройства (аутентификатора) и по сети не передаются.
Использование этого протокола позволяет выполнять безопасную аутентификацию через браузер на мобильном устройстве с распознаванием на устройстве лица или отпечатка пальца, что сопоставимо по удобству с мобильными приложениями.
В основе протокола WebAuthN лежит надёжная асимметричная криптография (криптография с открытым ключом).
Создание ключей и аутентификация по протоколу WebAuthN
Для регистрации открытого ключа пользователя в UIDM пользовательским устройством создаётся закрытый (приватный) ключ и открытый (публичный) ключ, которые вместе называются ключевой парой.
Закрытый (приватный) ключ используется пользователем для подписания направляемых им сообщений.
Открытый (публичный) ключ используется сервером для проверки подписи полученных сообщений. Успешная проверка подписи сообщения от пользователя доказывает, что полученные сервером сообщения направлены владельцем закрытого ключа (пользователем).
Закрытый ключ сохраняется на пользовательском устройстве в защищённом хранилище аутентификатора (программного компонента или устройства).
Открытый ключ вместе со идентификатором (логином) пользователя направляется на сервер и сохраняется на нём[1].
Аутентификация пользователя на защищаемом ресурсе по протоколу WebAuthN означает доказывание того, что авторизующийся пользователь владеет закрытым ключом, соответствующим ранее направленному на сервер открытому ключу.
Аутентификатор (программное обеспечение или устройство) при выполнении процедуры аутентификации должен проверить физическое присутствие пользователя и его согласие на совершение операции. Аутентификатор может выполнять распознавание биометрических данных.
Аутентификация (доказывание владения закрытым ключом) выполняется следующим образом:
-
сервер направляет стороне, запрашивающей аутентификацию, challenge (случайное число);
-
запрашивающая аутентификацию сторона (пользователь) подписывает это число закрытым ключом из ключевой пары, созданной для аутентификации на этом ресурсе;
-
сервер, получив ответ запрашивающей стороны, проверяет его подпись при помощи хранящегося на сервере открытого ключа пользователя, которым сервер располагает после выполнения процедуры регистрации открытого ключа;
-
успешная проверка подписи при помощи открытого ключа подтверждает владение стороны, запрашивающей аутентификацию, закрытым ключом этого пользователя; этим подтверждается подлинность пользователя.
При аутентификации по протоколу WebAuthN может предоставляться сертификат ключевой пары, выданный третьей доверенной (удостоверяющей) стороной. Открытый ключ пользователя, направляемый на сервер, подписывается удостоверяющей стороной (закрытым ключом). Сервер, используя открытый ключ удостоверяющей стороны, проверяет подпись удостоверяющей стороны.
Сценарии с использованием протокола WebAuthN
Регистрация устройства для аутентификации на основе биометрических данных
-
Выполнена аутентификация пользователя (в браузере сохранён токен доступа).
-
Устройство поддерживает технологию WebAuthN.
-
Пользователь переходит на страницу управления способами аутентификации.
-
Браузер отображает элемент пользовательского интерфейса (кнопку), указывающий на возможность привязать устройство.
-
При нажатии на кнопку выполняется запрос API: Инициализация сценария привязки для получения параметров электронной подписи. Текущий токен доступа передается браузером автоматически.
-
Сервер генерирует случайное число (
nonce
) и возвращает его в ответе. -
Клиентский код вызывает метод
credentials.create()
. -
Пользователь разрешает генерацию ключевой пары и выполняет другие действия, которые ему предлагает операционная система (например, прикладывает палец к сканеру отпечатка пальца или выполняет распознавание лица). Серверу возвращаются объекты
clientJson
,attestation
. -
Браузер выполняет запрос API: Привязка нового ключа на регистрацию открытого ключа. Передаются
execution
,clientData
,attestation
. -
Сервер выполняет проверки
clientData
,attestation
в соответствии со спецификацией WebAuthN. -
Сервер создает запись в таблице CertificateCredentials, в которой открытый ключ ассоциируется с логином пользователя.
Аутентификация на ранее зарегистрированном устройстве
-
Пользователь выполнил регистрацию на этом устройстве.
-
Пользователь переходит на страницу выбора способа аутентификации.
-
Браузер отображает элемент пользовательского интерфейса (кнопку), указывающую на возможность аутентификации по протоколу WebAuthN.
-
При нажатии выполняется запрос API: Инициализация сценария аутентификации на получение параметров подписания. Текущий токен доступа передается браузером автоматически.
-
Сервер генерирует случайное число (
nonce
) и возвращает его в ответе. -
Клиентский код вызывает метод
credentials.get()
. -
Пользователь разрешает использование закрытого ключа (генерацию электронной подписи) и выполняет другие действия, которые ему предлагает операционная система (например, прикладывает палец к сканеру отпечатка пальца или выполняет распознавание лица). Возвращается объект аутентификатора.
-
Браузер выполняет запрос API: Аутентификация с открытым ключом из ключевой пары на аутентификацию с использованием протокола WebAuthN. Передаются
execution
,credentialId
,authenticatorData
,clientData
,userHandle
,signature
. -
Сервер выполняет проверки переданных данных в соответствии со спецификацией WebAuthN.
-
Сервер выполняет поиск в таблице CertificateCredentials. Если открытый ключ зарегистрирован, аутентификация считается успешной.
-
Сервер вызывает сервис
auth
, находящийся в составе Digital Back, метод/auth/user/:id
. -
Выполняется запись события аутентификации в БД аудита.
-
Выпускаются и возвращаются токен доступа, токен обновления доступа.
Спецификация API
Создание ключевой пары и привязка открытого ключа к идентификатору пользователя
Инициализация сценария привязки
POST {host}/{webauthn-endpoint-path}/webauthn/addInitiate
Content-Type: application/json
Accept: application/json
Cookie: at=...
Часть пути эндпоинта настраивается: значение {webauthn-endpoint-path}
устанавливается настройкой окружения экземпляра UIDM.
Cookie авторизации с префиксом подставляется браузером автоматически.
Наименование префикса, добавляемого к cookie авторизации, настраивается: его
значение устанавливается настройкой окружения экземпляра UIDM. Значение
префикса по умолчанию — at
.
Тело запроса отсутствует.
HTTP 200 OK
{
"continuationKey": "b409234f-25b5-4e7f-b632...",
"approvalInfo": {
"serverNonce": "1234",
"rpId": "uidm.ru",
},
"form": { ... },
"status": "approval_required"
}
Наличие в ответе поля status
со значением approval_required
означает, что
можно перейти к шагу API: Привязка нового ключа.
Из ответа на запрос необходимо сохранить значение атрибута continuationKey
.
Также из ответа необходимо сохранить значения полей rpId
и serverNonce
и передать их в качестве значений для параметров rpId
и challenge
методу
create()
WebAuthN.
Привязка нового ключа
POST {host}/uidm-webapi-1/webauthn/add
Content-Type: application/json
Accept: application/json
Cookie: at=...
{
"continuationKey": "...",
"attestation": "...",
"clientData": "..."
}
Переменная | Описание | Комментарий |
---|---|---|
|
Токен поддержания сценария |
Передается последний полученный от сервера |
|
Base64-кодированная строка |
https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorAttestationResponse/attestationObject |
|
Base64-кодированная строка |
https://developer.mozilla.org/en-US/docs/Web/API/AuthenticatorResponse/clientDataJSON |
HTTP 200 OK
{
"status": "done"
}
Наличие в ответе поля status
со значением done
означает, что публичный
ключ успешно привязан к идентификатору пользователя.
Аутентификация на основе протокола WebAuthN
Инициализация сценария аутентификации
POST {host}/sso/oauth2/access_token
Content-Type: application/x-www-form-urlencoded
Accept: application/json
client_id=oauth_front_m2m&
client_secret=password&
realm=/customer&
grant_type=urn:roox:params:oauth:grant-type:m2m&
service=login-by-Webauthn
Переменная | Описание | Комментарий |
---|---|---|
|
Идентификатор приложения |
|
|
Секрет приложения |
Передается, если сейчас работает m2m-протокол. Если |
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
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
даны условно.
Переменная | Описание | Комментарий |
---|---|---|
|
Идентификатор приложения |
|
|
Секрет приложения |
Передается, если сейчас работает m2m протокол. Если |
|
Токен поддержания сценария |
Передается последнее значение |
|
Идентификатор |
|
|
Base64-кодированная строка |
|
|
Base64-кодированная строка |
|
|
UTF-8 cтрока |
Пример преобразования: var decoder = new TextDecoder("utf-8"); function ab2str(buf) { return decoder.decode(new Uint8Array(buf)); } Кодировка Base64 здесь не используется, поскольку это строка в кодировке UTF-8. |
|
Base64-кодированная строка |
HTTP 200 OK
{
"access_token": "..."
}
Наличие токена доступа (access_token
) в теле ответа означает, что
аутентификация выполнена успешно.