Пользовательские модули аутентификации
Authd — это сервис аутентификации с возможностью настройки различных факторов. Для аутентификации Authd может использовать один или несколько факторов (плагинов). Без выбранного фактора Authd отрабатывает корректно и аутентифицирует без каких либо запросов. Однако в целях безопасности на данный момент для всех прошивок по умолчанию в качестве фактора задан пароль.
Настройка списка факторов выполняется индивидуально для каждого пользователя администратором в системном приложении Настройки.
Authd сканирует каталог /usr/lib/authd/, чтобы найти установленные в систему факторы (плагины .so).
Authd содержит в себе:
- сервис;
- плагины (список может пополняться):
- Блокировка;
- Ограничение входа в систему;
- Пароль;
- Смарт-карта;
- Простое подтверждение (пакет authd-tests);
- консольное приложение auth-cli, которое позволяет проверять пароль из командной строки.
Каждый плагин реализует собственный фактор аутентификации.
Authd поддерживает API блокировок через D-Bus-интерфейс.
У каждого пользователя есть свой список факторов. Настройка списка факторов выполняется индивидуально для каждого пользователя администратором в системном приложении «Настройки».
Содержание:
- Процесс аутентификации
- Типы клиентов
- Типы плагинов
- Конфигурация AuthService
- Текущее состояние AuthService
- Разработка нового плагина
- Использование Authd
Процесс аутентификации
Клиент подключается к сервису AuthService с помощью локального unix-сокета
/var/run/authd/authd.socket
и выполняет запрос RequestChallenge
.
AuthService генерирует случайный идентификатор, привязывает его к имени подключения
и возвращает клиенту.
Используя этот идентификатор, клиент делает запрос Authenticate
.
AuthService определяет пользователя, от имени которого выполнен запрос, и последовательно вызывает
метод authenticate
для каждого выбранного у данного пользователя фактора.
Обработчик метода authenticate
может запросить ввод пользовательских данных, тогда AuthService
транслирует запрос на отображение формы ввода зарегистрированному сервису AuthUiClient.
В настоящий момент для каждого процесса, в рамках которого выполняется аутентификация, необходимо зарегистрировать свой AuthUiClient. В рамках обработки запроса AuthUiClient отображает форму ввода, специфичную для текущего фактора.
После ввода пользователем данных AuthUiClient возвращает их с помощью SetResponse
и они
передаются для проверки.
Если данные корректны, AuthService переходит к следующему фактору.
Если факторов больше нет, и все предыдущие проверки были успешны, генерируется
аутентификационный токен и отправляется клиенту.
Используя этот токен, клиент может делать привилегированные запросы.
Типы клиентов
В текущей реализации поддерживаются следующие типы клиентов:
unlock-ui
Разблокировка шифрованного раздела с домашними директориями пользователей (/home) во время загрузки мобильного устройства. Для первого фактора, запросившего ввод пользователя, отображается соответсвующая страница UI. Пользователь вводит данные этого фактора. Эти данные перехватываются authd, используются для разблокировки /home и кешируются.lipstick
Разблокировка экрана во время работы мобильного устройства.settings
Подтверждение привилегированного действия администратором в приложении Настройки.
В дальнейшем, в зависимости от типа клиента могут использоваться разные списки факторов.
Типы плагинов
Плагины Authd могут быть трёх типов:
- Явными — проверки аутентификации требуют взаимодействия с пользователем. Пример: ввод пароля.
- Неявными — проверки аутентификации выполняются без взаимодействия с пользователем. Пример: вход по дням недели.
- Не аутентифицирующими — данный тип плагина не реализует функции аутентификации. Используется для выполнения привилегированных действий после прохождения аутентификации. Например, для сброса устройства к заводским настройкам.
Конфигурация AuthService
При старте AuthService читает конфигурационный файл /etc/authd/authd.conf
.
С помощью данного файла можно настроить списки обязательных, выбранных по умолчанию и неизменяемых
факторов для администратора и пользователей.
Конфигурационный файл имеет секции [worker]
и [devlock]
.
Секция [worker]
В секции [worker]
читаются следующие опции:
Опция | Описание |
---|---|
admin-mandatory-factors |
Список обязательных факторов для администратора (defaultuser ) |
admin-immutable-factors |
Список факторов для администратора, которые не могут быть включены или отключены |
admin-default-factors |
Список факторов по умолчанию для администратора. Этот список применяется, если у администратора не выбран ни один из факторов |
user-mandatory-factors |
Список обязательных факторов для обычных пользователей |
user-immutable-factors |
Список неизменных факторов для обычных пользователей |
user-default-factors |
Список факторов по умолчанию для обычных пользователей |
В списках должны быть указаны внутренние имена факторов через запятую. По умолчанию все списки пусты. Внутренние имена перечислены в следующей таблице:
Внутреннее имя | Описание | Тип |
---|---|---|
lockout |
Блокировка устройства | Implicit |
loginrestriction |
Расписание входа пользователя | Implicit |
confirm |
Простое подтверждение да/нет (тестовый плагин) | Auth |
password |
Пароль в luks-слоте шифрованного раздела | Auth |
reset |
Сброс устройства к заводским настройкам | Non-auth |
smartcard |
Смарт-карта (opensc-совместимая USB или NFC) | Auth |
Неинтерактивные факторы выбираются автоматически, в Настройках они отсутствуют.
[devlock]
Опция | Описание |
---|---|
permissive-mode |
Включить аутентификацию пользователя, даже если какой-то фактор не сработал (удобно для отладки) |
Пример
Пример конфигурационного файла /etc/authd/authd.conf
:
[worker]
admin-mandatory-factors = password
admin-immutable-factors = password, confirm
user-default-factors = password
[devlock]
permissive-mode = true
Текущее состояние AuthService
Списки выбранных факторов для пользователей хранятся в директории
/var/lib/authd/users/ в файлах с именем вида
Редактирование файлов конфигурации не поддерживается во время работы Authd, потому что любое подобное изменение будет потеряно.
Разработка нового плагина
В операционную систему могут быть добавлены новые плагины, что позволяет расширить выбор факторов аутентификации или выполняемых привилегированных действий без изменения кода AuthService. Для этого необходимо сформировать rpm-пакет, включающий:
- Плагин, обращающийся к AuthService и выполняющий проверку введённых данных
(разделяемая библиотека .so).
Плагин должен содержать:
- Файлы
.json и method-.cc . Файлы обязательны для всех типов плагинов. Библиотека .so должна содержать реализацию методов базового класса AuthPluginInterface, в том числе, метод authenticate. - Файл policy.conf, задающий число попыток пользователя для связи (этот файл специфичен для плагинов).
- Файлы
- QML-плагин для использования в QML-форме ввода данных для взаимодействия с AuthService
(разделяемая библиотека .so).
Плагин должен содержать:
- Файл страницы для аутентификации MethodPage
.qml обязателен для явного плагина и опционален для неявного. - Файл
Info.qml , является вспомогательным для предыдущего и нужен для отображения сообщений на страничке MethodPage.qml и сообщений об ошибках на общей для всех плагинов страничке AuthFailed.qml. - Файл настроек плагина settings-
.cc обязателен для явного плагина. Файл (Важно чтобы на выходе получился корректный qml-плагин (тоже *.so, но отличный от *.so authd-плагина), который можно использовать на своей страничкеSectionItem.qml в «Настройках») и опционален для других типов;
- Файл страницы для аутентификации MethodPage
- Каталог настроек settings.
Каталог опционален для всех типов плагинов и должен содержать:
- Файл settings.pro.
- Каталог
-settings с файламиSectionItem.qml ,Settings.qml ,auth.json .
Требования к API плагина
С точки зрения плагина процесс аутентификации выглядит следующим образом:
- Старт аутентификации со стороны AuthService (если данный фактор выбран у пользователя).
- При необходимости плагин запрашивает ввод пользователя с помощью Qt-сигнала
inputRequested
. AuthService передаёт запрос зарегистрированному AuthUiClient, который отображает UI-страницу с соответствующей формой ввода. - После ввода пользовательские данные отправляются AuthService и передаются плагину для проверки.
- Результат проверки возвращается AuthService с помощью Qt-сигнала
methodFinished
, в случае ошибки передаётся код, который транслируется в строку с переводом. - Если результат проверки успешный, то AuthService переходит к следующему фактору.
AuthService ожидает, что плагин имеет обработчики следующих запросов:
- Authd-плагин (библиотека .so, реализующая методы AuthPluginInterface).
- Непривилегированный процесс, запускаемый плагином в контейнере (<название_плагина>-клиент), который реализует описанные методы.
- Аутентификация
authenticate
. - Получение и установка глобальной опции:
getOption
,setOption
. - Получение и установка пользовательской опции:
getUserOption
,setUserOption
. - Выполнение глобальных привилегированных действий:
action
. - Выполнение пользовательских привилегированных действий:
userAction
.
Пользовательские опции отличаются от глобальных привязкой к идентификатору заданного пользователя.
При запросе незнакомой опции методы getOption
и getUserOption
должны вернуть пустой variant
,
а setOption
и setUserOption
— false
.
API методов плагина
QVariantMap readyForAuthentication()
Метод позволяет получить информацию о том, что клиент готов к аутентификации и узнать страницу, которую нужно видеть при аутентификации.
Ответ:
bool res
— готов/не готов;QString page
— c помощью какой страницы аутентифицироваться;
Варианты ответов могут расширяться.
QVariantMap authentificate(QVariantMap param)
Метод проверяет вводимые данные, при успехе происходит аутентификация.
param
содержит данные для аутентификации.
Примеры:
{ "pin": text }
{ "password": text }
{ "cert": text, "pin": text }
Ответ:
bool res
— успешно/не успешно;QString err
: "success", "failure", "login locked", "password expired", "no network connection";
Варианты ответов могут расширяться.
Клиент может присылать текущее количество неуспешных попыток: uint attempts
.
QString validateCert(const QString &certName, const QString &userLogin, const QString &pin)
Метод производит проверку по логину, PIN и сертификату, при успехе происходит аутентификация.
certName
— сертификат, выбранный из списка, переданногоgetCertList
;userLogin
— логин текущего пользователя;pin
— PIN-код от сертификата.
Ответ:
QString err
: "success", "failure", "login locked", "password expired", "no network connection", "cert is not valid".
Требования к файлам плагина
Файл .json
Файл PluginInfo
при загрузке плагина.
Структура файла:
{
"Name": "имя плагина",
"Descr": "Описание плагина",
"Page": "Страница для аутентификации (если тип плагина явный, т. е. auth)",
"Version": "Номер версии (например, 0.0.1)",
"Type": "Тип плагина — auth/implicit/non-auth",
"Priority": "Порядковый номер приоритета процесса"
}
Название плагина указывается в нижнем регистре и используется в названиях каталогов и файлов (см. структуру плагина выше). Название страницы обычно соответствует названию плагина, но пишется в CamelCase. Оно используется в названии qml-файлов (см. структуру плагина выше).
Пример для явного плагина:
{
"Name": "myplugin",
"Descr": "Описание",
"Page": "MyPlugin",
"Version": "0.0.1",
"Type": "auth",
"Priority": 10
}
Пример для неявного плагина:
{
"Name": "myplugin",
"Descr": "Описание",
"Page": "MyPlugin",
"Version": "0.0.1",
"Type": "implicit",
"Priority": 50
}
Пример для не аутентифицирующего плагина:
{
"Name": "myplugin",
"Descr": "Описание",
"Page": "",
"Version": "0.0.1",
"Type": "non-auth",
"Priority": 50
}
Файл method-.cc
Файл method-
Файл policy.conf
Чтобы задать максимальное возможное число попыток пользователя связаться с плагином,
нужно создать файл policy.conf и задать значение max-attempts
:
max-attempts=7
Данный файл должен размещаться по пути
/usr/share/ru.<имя_организации>.
Его можно разместить по данному пути, добавив
в .spec-файл
в секции %install
и %files
строки:
%install
install -D -m 0644 policy.conf %{buildroot}/usr/share/ru.<имя_организации>.<plugin>_client/policy.conf
%files
...
/usr/share/ru.<имя_организации>.<plugin>_client/policy.conf
Значение attempts
для текущего пользователя
Текущее значение max-attempts
, если оно меняется на сервере в процессе работы, размещается
в файле /srv/shared/ru.<имя_организации>/
Файлы MethodPage.qml и Info.qml
MethodPage
Страница обязательно содержит в корневом элементе js-функции:
function infoMessage(id)
— функция возвращает текстовое сообщение для пользователя в процессе аутентификации, например, просьбу ввести пароль, придумать новый и т. п.;function resultMessage(id)
— функция возвращает текстовое сообщение для пользователя об итогах аутентификации, например, об успехе или ошибке.
Файл settings-.cc
settings-
Каталог settings
Каталог settings хранит набор файлов для приложения «Настройки»
в
Настройки могут быть общими и пользовательскими.
Файл в settings settings.pro содержит пути:
- для общих настроек
path = /usr/share/jolla-settings/pages/users/general
; - для пользовательских настроек
path = /usr/share/jolla-settings/pages/users/user-settings
.
Пример pro-файла:
TEMPLATE = aux
settings.path = /usr/share/jolla-settings/pages/users/general
settings.files = password-settings
management.path =/usr/share/jolla-settings/pages/users/user-settings
management.files = passwords-management
INSTALLS += settings management
OTHER_FILES += *.qml *.json
Каталог
SectionItem.qml — секция в настройках;Settings.qml — страница с настройками, которая открывается при нажатии на секцию;auth.json — конфигурация для связи секции и страницы настроек.
Файл с именем <Plugin-name>SectionItem.qml
добавляет пункт меню
в «Настройках безопасности пользователя».
Файл с именем <Plugin-name>Settings.qml
— страницу, которая откроется при нажатии
на этот пункт меню.
Пример MyPluginSectionItem.qml:
import QtQuick 2.0
import Sailfish.Silica 1.0
import com.jolla.settings.system 1.0
SectionItem {
name: qsTr("Password Settings")
description: qsTr("Password policy settings")
}
Пример mypluginauth.json:
{
"page": "MyPluginSettings.qml",
"item": "MyPluginSectionItem.qml",
"order": 400
}
Использование Authd
Плагин Authd можно использовать на странице для подтверждения/аутентификации.
Для его использования в qml необходимо подключить библиотеку authclient
:
import ru.omp.authclient 1.0
Компоненты для аутентификации:
AuthQuery {
id: query
}
AuthUi {
id: authUi
registered: true
}
Пример запуска для действия, например, нажатия кнопки:
onClicked: {
query.authenticate(function() {
//действие при успехе
}, function() {
// если аутентификация не была пройдена
})
}
Если аутентификация должна быть запущена из диалога:
const obj = SettingsUtils.openDialogPage(Qt.resolvedUrl("NameDialog.qml"),
{ acceptDestination: query.tokenIsValid
? root
: root.authUi,
acceptDestinationAction: query.tokenIsValid
? PageStackAction.Pop
: PageStackAction.Replace })
obj.pageCompleted.connect(function(dialog) {
dialog.accepted.connect(function() {
//действие при успехе
}, function() {
// если аутентификация не была пройдена
})
})