Python. Двухфакторная авторизация через Google Authenticator

Последние годы стало модно делать двухфакторную авторизацию, это безусловно повышает безопасность приложений и сайтов в частности, сегодня я расскажу как сделать дополнительную авторизацию через TOTP. В качестве клиента будем использовать мобильную версию Google Authenticator для Android.
Для этого нам понадобится два файла:
- "totp.py" - собственно реализация алгоритма TOTP;
- "totp_auth.py" - хелпер для генерации и валидации токенов.
Пример работы
Создадим изолированное окружение, установим зависимости:
mkdir ~/work/totp && cd ~/work/totp wget -O totp.py wget -O totp_auth.py virtualenv --no-site-packages --distribute venv . venv/bin/activate pip install qrcode PIL
Создадим файл sample.py для демонстрации работы, со следующим содержимым:
Разберем работу sample.py. Сначала идет шаг регистрации двухфакторной авторизации пользователя и сохранения секретного ключа (SECRET):
- Генерируем новый секретный ключ (SECRET);
- Выводим QR-код;
- Пользователь его сканирует через Google Authenticator;
- Вводит в форму ввода на сайте полученный от Google Authenticator токен;
- Если Пользователь ввел правилный токен, то мы сохраняем секретный ключ (SECRET) этому пользователю в БД, чтобы при авторизации использовался этот ключ для валидации токенов с Google Authenticator.
Запускаем:
$ python sample.py SECRET: UG4QTQ6F4JI4BE3Y

Please input the token from Google Authenticator: 123123 FAILED (тут специально пользователь ввел неверный токен) Please input the token from Google Authenticator: 613257 SUCCESS (тут пользователь ввел верный токен, сохраняем SECRET в БД)
Теперь разберем шаги авторизации:
- Пользователь входит на сайт и вводит правильные логин и пароль;
- Если мы однозначно идентифицируем пользователя и для него уже есть секретный ключ (SECRET) в БД, то выводим ему QR-код по этому секретному ключу;
- Он сканирует QR-код через Google Authenticator, либо среди свои аккаунтов находит уже созданный и вводит текущий токен на сайте;
- Если он за указанное время ввел токен, то авторизация считается успешной иначе ему предлагается повторить попытку.
Запускаем с секретным ключем:
$ python sample.py UG4QTQ6F4JI4BE3Y SECRET: UG4QTQ6F4JI4BE3Y

Please input the token from Google Authenticator: 123123 FAILED (тут специально пользователь ввел неверный токен) Please input the token from Google Authenticator: 394500 SUCCESS (тут пользователь ввел верный токен, можно его авторизовывать)
Таким образом мы реализовали двухфакторную авторизацию на базе TOTP и Google Authenticator. Постараюсь в ближайшее время на базе этой статьи сделать приложение для Django, которое будет хранить секретные ключи в БД и выводить QR-код когда это необходимо.
Комментарии
Есть для джанги уже django-secureauth
Да, для джанги уже куча таких либ, я уже решил ничего не писать
https://github.com/Bouke/django-two-factor-auth
https://github.com/mtigas/django-twofactor
Я для себя написал следующий код:
Оставьте свой комментарий