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

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

Для начала разберем общий план. Какие же шаги нужно реализовать в нашем бизнес-процессе?

  1. Проверка логина (убедиться, что пользователь действительно зарегистрирован).
  2. Проверка правильности пароля.
  3. Отправка кода подтверждения по почте или смс.
  4. Проверка актуальности кода.
  5. Проверка правильности кода.
  6. Завершение аутентификации.

Подготовительный этап

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

  • В данных пользователя обязательно содержится емейл. Он будет использован для отправки проверочного кода. Часто емейл используется в качестве логина и мы рассмотрим именно такой пример.
  • Логин является уникальным. В системе не могут существовать два разных пользователя с одинаковым логином.

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

auth module

Проверка логина

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

user check

Для этого блоком DB: Search User выполняется поиск пользователя с данным логином в БД. Обязательно установить параметр SearchExact = True для поиска точного совпадения.

Полученные данные передаются в блок Array Element с индексом равным 0 (отсчет начинается с нуля и единственное найденное значение всегда будет соответствовать индексу 0 в массиве).

Блок Is Null выполняет проверку - действительно ли пользователь был найден. И, в зависимости от результата (True/False), блок If-Else либо прервет бизнес процесс, с выводом сообщения об ошибке (блок Raise Error), либо направит его дальше.

Проверка пароля

На данном этапе необходимо убедиться в том, что пароль пользователя введен верно.

password check

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

По этой причине нельзя просто достать пароль из базы и сравнить его с введенным паролем. Необходимо получить хеш пароля и использовать для сравнения именно его. Для решения данной задачи используется блок Auth: Probe Password. В качестве входных параметров он использует пароль введенный пользователем (password) и хеш пароля, сохраненный в БД (hashed_password) и преобразованный в тип данных String (блок To String).

В зависимости от результата, как и на предыдущем шаге, с помощью блока If-Else, либо выводим сообщение об ошибке (Raise Error, Message = Password is wrong), либо направляем процесс на следующий этап.

Дополнение модели пользователя

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

Вообще модель User изначально содержит поля, которые можно использовать для этой задачи - Confirmed, Confirmation code, Confirmation code expires at. Но в рассматриваемом примере мы будем исходить из того, что данные поля используются только для регистрации и первоначального подтверждения учетной записи.

Для большей наглядности процесса создадим отдельную модель twofa (two-factor authentication), свяжем модель User с ней (связь 1-к-1, has one) и добавим одно поле code (тип String).

user model

Подготовка к отправке писем

Для отправки писем с кодами подтверждения необходимо выполнить предварительную подготовку. Одним из самых простых вариантов является использование модуля Custom SMTP, нужно установить его и настроить.

custom SMTP module

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

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

Отправка кода подтверждения

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

send email

В качестве адресата блок Custom SMTP: Send Email использует массив адресов. Поэтому, несмотря на то, что отправить письмо нужно только на один адрес, его следует добавить в массив. Для этого используется блок Append Array.

Следующий шаг - создание кода подтверждения. Для этого подойдет блок Random string. Будем отправлять код, состоящий из 6 случайных цифр и сделаем соответствующие настройки. Length = 6, With 0-9 = True, все остальные параметры = False.

Далее нужно сформировать текст письма. Для этого с помощью блока Concat Strings добавим поясняющий текст к созданному коду (First = Verification code: ), преобразуем полученный результат в тип данных Text (блок To Text) и соединим результат с параметром body блока отправки письма.

Для итоговой отправки остается только указать тему письма (subject) и отправителя (from_name).

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

save twofa

Для этого воспользуемся моделью twofa, которую предусмотрительно создали ранее. В случае, если это первая отправка кода, необходимо создать ее с указанием информации о том, к какому пользователю она относится. В случае повторного использования необходимо пропатчить существующую запись, указав ее ID и новый код.

Финальным шагом этапа является использование блока Raise Error для возврата сообщения об отправке кода на почту.

Проверка актуальности кода

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

code lifetime check

Воспользуемся блоком Current date & time для получения текущего времени. Соединим его с параметром B блока Date & time difference. В качестве параметра A будем использовать поле UpdatedAt модели twofa.

В результате получим Time span - разницу между двумя временными точками. Останется лишь проверить превышает ли эта разница определенное выбранное значение. В нашем примере это 5 минут, которые и установим в качестве статического значения B блока Greater.

time span value

Блок If-Else воспользуется результатом сравнения для дальнейшего направления процесса. В случае True (разница превышает 5 минут) произойдет возврат к шагу отправки письма, пользователь получит обновленный код. В случае False (код свежий и актуальный) можно будет перейти к проверке данного кода.

Проверка кода

Завершающий этап аутентификации - проверка полученного кода.

code check

Блок Equal должен подтвердить совпадение кода переданного пользователем и кода сохраненного в модели twofa связанной с пользователем. Если это не так и код указан неверно (If-Else -> False), то нужно вывести сообщение об ошибке (Raise Error, Message = Code is wrong). Если же сравнение подтвердит совпадение, то можно переходить к финальному этапу аутентификации.

Для этого используем блок Auth: Authentication и получаем информацию о пользователе с его токеном авторизации. Их передаем в блок End, как результат успешного прохождения аутентификации.

Создание эндпойнта

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

2fa endpoint

Разумным решением будет использовать эндпойнт аутентификации, созданный по умолчанию (POST /Auth). Достаточно будет всего лишь заменить его бизнес-процесс и установить тот, который был только что создан. Таким образом простая аутентификация будет отключена и вместо нее начнет использоваться двухфакторная.

Публикация и тестирование

На этом создание двухфакторной аутентификации полностью завершено. Можно опубликовать результат и проверить его в деле. Для этого удобно использовать Swagger, доступ к которому можно получить нажав на название Deploy-плана в разделе Project API кнопки Preview.

project API

Остается лишь найти нужный эндпойнт в списке, ввести данные пользователя и запустить выполнение кнопкой Execute. Если же при тестировании обнаружатся какие-то ошибки, то вернуться к бизнес-процессу и внести необходимые изменения.

Swagger

Was this article helpful?

AppMaster.io 101 Полный курс

10 модулей
2 недели

Не знаете с чего начать? Начните с нашего ускоренного курса для начинающих и изучите AppMaster от А до Я.

Начать обучение
Development it’s so easy with AppMaster!

Остались вопросы?

Наши эксперты с радостью ответят на все ваши вопросы о платформе AppMaster и помогут вам в создании приложений.

headphones

Служба поддержки

Поделитесь своей проблемой с нашими специалистами.

message

Комьюнити AppMaster

Обсудите вопросы с другими пользователями в нашем чате.

Присоединиться