Работа с одноразовыми паролями в Go

Работа с одноразовыми паролями в Go


Начнем с простой заготовки программы, которая в браузере показывает сообщение “hello”.

Здесь все стандартно.

Компилируем программу, запускаем, открываем браузер, вводим адрес http://127.0.0.1:3000.

Исходник можно посмотреть тут.

Страница авторизации

Добавим шаблон главной страницы. Создаем файл templates/index.html

Шаблон максимально упрощён. Мы не используем все необходимые теги html.

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

Компилируем. Запускаем. Проверяем.

Теперь надо добавить обработчик запросов, на который будут отправляться данные формы авторизации POST-запросом.

Компилируем. Запускаем. Проверяем. После успешной авторизации под пользователем zaz600 с паролем 123 мы должны увидеть следующее:

Исходник можно посмотреть тут.

Подключаем шаблон для настройки 2ФА

В конец шаблона templates/index.html добавляем ссылку для перехода на страницу, где будет отображаться QR-код, с помощью которого аккаунт можно добавить в Яндекс.Ключ.

Создаем новый шаблон templates/2fa.html

Подключаем новый шаблон.

Компилируем, запускаем, проверяем.

QR-код отсутствует, так как мы его еще не сгенерировали.

Исходник можно посмотреть тут.

Генерируем QR-код

Для работы с одноразовыми паролями будем использовать библиотеку https://github.com/pquerna/otp. Скачиваем её.

go get github.com/pquerna/otp

Генерируем картинку с кодом настройки.

Компилируем, запускаем, проверяем.

Исходник можно посмотреть тут.

Проверяем настройку 2ФА

После того, как QR-код был отсканирован и добавлен в Яндекс.Ключ, тот начнет генерировать одноразовые пароли каждые 30 секунд.

Нам необходимо проверить код, который сгенерирует Яндекс.Ключ. Иначе нельзя считать, что пользователь завершил процедуру перехода на одноразовые пароли.

Для завершения настройки вводим код и нажимаем кнопку Verify. Напишем обработчик, проверяющий этот код.

Компилируем. Запускаем. Сканируем QR-код, вводим одноразовый пароль и жмем Verify.

Исходник можно посмотреть тут.

Проверяем одноразовые пароли

Теперь добавим проверку одноразового кода при аутентификации на главной странице.

Добавляем возможность ввода кода при авторизации в шаблон templates/index.html

И проверяем одноразовый пароль.

Компилируем. Запускаем. Добавляем аккаунт в Яндекс.Ключ, вводим код. Переходим на главную страницу. Вводим логин (zaz600), пользовательский пароль(123) и одноразовый пароль из Яндекс.Ключа. Если всё верно, то увидим приветствие.

Исходник можно посмотреть тут.

Заключение

Различные сервисы используют одноразовые пароли по-разному. Одни требуют ввести логин, пользовательский пароль, а затем одноразовый код (Вконтакте). Другие требуют ввести логин и сразу одноразовый пароль, как делает Яндекс. Тут надо понимать, что Яндекс в своем Ключе генерируемые одноразовые пароли защищает дополнительным ПИН-кодом, без ввода которого невозможно получить одноразовый пароль.

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

Импортировать библиотеку github.com/pquerna/otp

Сгенерировать TOTP ключ для пользователя. key,_ := totp.Generate(…).

Отобразить пользователю Секретный код ключа и QR-код. User. key.Secret() и key.Image(…).

Проверить, что пользователь успешно настроил использование одноразовых паролей. totp.Validate(…).

Сохранить в базе/файле key.Secret()

Сгенерировать пользователю аварийные коды восстановления (см. ниже)

Проверка одноразовых кодов

Проверить логин и пароль пользователя как обычно.

Если у пользователя настроена 2ФА через TOTP, запросить одноразовый код.

Загрузить TOTP Secret из базы.

Проверить код, который ввел пользователь totp.Validate(…)

Аварийные коды

Если пользователи потеряют доступ к устройству генерации TOTP, они больше не будут иметь доступ к своей учетной записи в вашей системе. Поскольку TOTP часто бывают настроены на мобильных устройствах, которые могут быть потеряны, украдены или повреждены, это проблема возникает часто. По этой причине многие сайты предоставляют своим пользователям “резервные коды” или “коды восстановления”. Это набор одноразовых временных кодов, которые могут быть использованы вместо TOTP. Они могут быть сгенерированы каждому пользователю, который перешел на 2ФА, случайным образом из букв и цифр и должны храниться в базе.


Надёжность

Из википедии:

TOTP достаточно устойчив к криптографическим атакам, однако вероятности взлома есть, например возможен такой вариант атаки «человек посередине»:

Прослушивая трафик клиента, злоумышленник может перехватить посланный логин и одноразовый пароль (или хеш от него). Затем ему достаточно блокировать компьютер «жертвы» и отправить аутентификационные данные от собственного имени. Если он успеет это сделать за промежуток времени X, то ему удастся получить доступ. Именно поэтому X стоит делать небольшим.

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





Report Page