Рубрики
Без рубрики

Реализация двухфакторной аутентификации с помощью Flask, Pyotp и Fauna

Написано в связи с программой записи с фауной. Эта статья фокусируется на реализации двух-FA … Теги с фауной, Python, Security, Serverless.

Написано в связи с Напишите с фауной программа

Эта статья посвящена реализации двухфакторной аутентификации в веб-приложении, созданном с Python и Flask с использованием встроенных функций аутентификации Fauna и PYOTP для создания и проверки одноразовых паролей.

Фауна является гибкой, удобной для разработчиков, транзакционной облачной базы данных, доставленной в виде безопасного API данных, которая предоставляет два интерфейса: GraphQL, а также язык запросов FAUNA (FQL), обеспечивая функциональность для хранения коллекций, индексов и других баз данных (много-кредитования). Он также предлагает встроенные функции аутентификации пользователей и управления сеансами. Чтобы узнать больше о фауне, Посетите официальную документацию Анкет

Эта статья включает в себя пошаговое руководство по интеграции функций аутентификации Фауны в веб-приложение Flask. Вы также добавите еще один уровень безопасности в аутентификацию пользователей и аутентификацию пользователей с несколькими факторами с использованием PYOTP. Чтобы узнать больше о PYOTP, Посетите официальную документацию Анкет

Создать базу данных фауны

Вам необходимо создать базу данных для веб -приложения на панели панели фауны. Если вы не создали учетную запись на фауне до сейчас, создайте одну на Сайт Фауны Анкет

На приборной панели нажмите на Новая база данных Кнопка, указать имя для вашей базы данных, затем нажмите Сохранить кнопка.

Создать коллекции баз данных

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

Чтобы создать коллекцию, перейдите к Коллекции Вкладка на боковой панели фауны (левая сторона экрана), нажмите на Новая коллекция Кнопка, предоставьте имя для коллекции, которую вы хотите создать, и нажмите Сохранить кнопка.

Создать индексы коллекции

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

Чтобы создать индекс, отправляйтесь в Индексы Вкладка на боковой панели фауны (левая сторона экрана), нажмите на Новый индекс Кнопка, предоставьте необходимую информацию и нажмите Сохранить кнопка.

Генерировать ключ безопасности базы данных

Теперь вам нужно создать Ключ безопасности Чтобы подключить вашу базу данных к любому приложению, используя любое из Водители Фауны Анкет Отправляйтесь в Безопасность Вкладка на боковой панели фауны (левая сторона экрана), нажмите на Новый ключ Кнопка, предоставьте необходимую информацию, а затем нажмите Сохранить кнопка.

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

Интеграция фауны в Python

Затем вам нужно получить драйвер Python для фауны. Вы можете установить его из Pip с одной линией в вашем терминале.

pip install faunadb

После этого вы должны запустить пример кода, предоставленного в Фауна питона документация драйвера Анкет

from faunadb import query as q  
from faunadb.objects import Ref  
from faunadb.client import FaunaClient   

client = FaunaClient(secret="your-secret-here")  

indexes = client.query(q.paginate(q.indexes()))  

print(indexes)

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

Теперь, когда вы успешно настроили свою базу данных Fauna и интегрировали сценарий Python, давайте начнем с веб-приложения и реализуя встроенную аутентификацию Fauna. Бэкэнд приложения будет построен с Колба , в то время как пользовательский интерфейс будет построен с Flask-Bootstrap .

Вы будете проектировать четыре (4) веб -страницы для приложения. Они есть:

  • Индекс/целевая страница
  • Регистрационная страница
  • Страница авторизации
  • Страница успеха аутентификации

Шаг 1: Установка требований проекта

Нам нужно установить библиотеку колбы и флез-бойдстрап. Мы сделаем это так же, как мы установили фауну ранее, используя PIP. В вашем терминале тип:

pip install Flask Flask-Bootstrap4

Шаг 2: Настройка сервера колбы

Создайте файл с именем app.py и сохранить в нем последующий код:

from flask import *
from flask_bootstrap import Bootstrap

app = Flask(__name__)
Bootstrap(app)


@app.route("/")
def index():
    return "Hello World!"


if __name__ == "__main__":
    app.run(debug=True)

Когда вы запускаете app.py Файл и откройте свой браузер, вы получите ответ, аналогичный изображению ниже:

Шаг 3: Разработка целевой страницы

Целевая страница – это то, где ваши пользователи видят информацию вашего приложения по навигационным ссылкам на различные маршруты в приложении.

Сначала создайте папку с именем Шаблоны В той же папке, что и ваш app.py Анкет Колба использует Шаблоны Папка для хранения своих HTML -файлов, которые сервер рендесирует в приложении. Ваша папка проекта должна напоминать изображение ниже:

Создайте другой файл с именем index.html который будет храниться в Шаблоны папка и сохранить в нем следующий код:

{% extends "bootstrap/base.html" %}

{% block content %}

Fauna Two-Factor Authentication (2FA) Demo

This is a Python + Flask demo application implementing two-factor authentication using Fauna's built-in authentication and PyOTP.
{% endblock %}

Вам также нужно обновить app.py Файл для реализации регистр Маршрут ссылается на целевой странице. Обновите app.py Файл с кодом ниже:

@app.route("/")
def index():
    return render_template("index.html")


@app.route("/register/")
def register():
    return "Register Page!"


@app.route("/login/")
def login():
    return "Login Page!"

Когда вы запускаете app.py Файл, вы получите ответ, как изображение ниже в вашем браузере:

Шаг 4: Создание страницы регистрации

Страница регистрации – это то, где ваши пользователи создают новые учетные записи в приложении.

Чтобы создать новые профили пользователей, которые Fauna поможет управлять аутентификацией, вам необходимо создать новый пользовательский документ в вашей коллекции, содержащей адрес электронной почты пользователя и пароль в параметре учетных данных. Вот пример кода Python, который демонстрирует эту функциональность:

client.query(
    q.create(
        q.collection("users"), {
            "credentials": {"password": "secret password"},
            "data": {"email": "test@test.com"}
        }
    )
)

Вам нужно обновить регистр маршрут внутри app.py файл для визуализации шаблона страницы регистрации; Обновите регистр маршрут с кодом ниже:

@app.route("/register/")
def register():
    return render_template("register.html")

Создайте другой файл с именем Register.html Это будет храниться в Шаблоны папка и сохранить в нем следующий код:

{% extends "bootstrap/base.html" %}

{% block content %}

Fauna Two-Factor Authentication (2FA) Demo

Create an account to get started!
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} {% endfor %} {% endif %} {% endwith %}
{% endblock %}

Когда вы запускаете app.py Файл, ваша страница регистрации должна напоминать изображение ниже:

Вам необходимо импортировать требуемые библиотеки, требуемые приложением. Обновите app.py Импорт файлов с помощью кода ниже:

from faunadb import query as q  
from faunadb.objects import Ref  
from faunadb.client import FaunaClient  
from faunadb.errors import BadRequest, Unauthorized

Вам также необходимо настроить конфигурации приложения (Fauna Secret Key, App Secret Key). Обновите app.py Файл с кодом ниже:

app.config["SECRET_KEY"] = "APP_SECRET_KEY"  
client = FaunaClient(secret="FAUNA_SECRET_KEY")

Далее вы обновите регистр Маршрут для записи новых деталей создания новых пользователей. Обновите app.py Файл с кодом ниже:

@app.route("/register/", methods=["GET", "POST"])
def register():
    if request.method == "POST":
        email = request.form.get("email").strip().lower()
        password = request.form.get("password")

        try:
            result = client.query(
                q.create(
                    q.collection("users"), {
                        "credentials": {"password": password},
                        "data": {"email": email}
                    }
                )
            )
        except BadRequest as e:
            flash("The account you are trying to create already exists!", "danger")
            return redirect(url_for("register"))

        flash(
            "You have successfully created your account, you can proceed to login!", "success")
        return redirect(url_for("register"))

    return render_template("register.html")

Шаг 5: Создание страницы аутентификации

Страница аутентификации – это то, где пользователи предоставляют свои учетные данные для приложения и предоставления авторизации.

Чтобы аутентифицировать хранимые профили пользователей с помощью Fauna, вам необходимо предоставить адрес электронной почты пользователя и пароль, а затем использовать Вход функция Вот пример кода Python, который демонстрирует эту функциональность:

client.query(
    q.login(
        q.match(q.index("users_by_email"), "test@test.com"), {
            "password": "secret password"}
    )
)

Создайте файл с именем Login.html Это будет храниться в рамках Шаблоны папка и сохранить в нем следующий код:

{% extends "bootstrap/base.html" %}

{% block content %}

Fauna Two-Factor Authentication (2FA) Demo

Login to access your account!
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} {% endfor %} {% endif %} {% endwith %}
{% endblock %}

Далее вы обновите Вход Маршрут для интеграции встроенной аутентификации Фауны в наше приложение. Обновите app.py Файл с кодом ниже:

@app.route("/login/", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        email = request.form.get("email").strip().lower()
        password = request.form.get("password")

        try:
            result = client.query(
                q.login(
                    q.match(q.index("users_by_email"), email), {
                        "password": password}
                )
            )
        except BadRequest as e:
            flash(
                "You have supplied invalid login credentials, please try again!", "danger")
            return redirect(url_for("login"))

        session["user_secret"] = result["secret"]
        return redirect(url_for("auth_success"))

    return render_template("login.html")


@app.route("/auth-success/")
def auth_success():
    return "

Successfully authenticated account using Fauna!

"

Шаг 6: Реализация правил авторизации в колбе

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

Вам нужно импортировать Functools Библиотека в приложение для создания пользовательских оберток для его маршрутов. Обновите app.py Импорт файлов с помощью кода ниже:

from functools import wraps

Далее вы обновите app.py Файл с приведенным ниже кодом для определения пользовательской обертки для обеспечения аутентификации пользователя:

def login_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if "user_secret" in session:
            try:
                user_client = FaunaClient(secret=session["user_secret"])
                result = user_client.query(
                    q.current_identity()
                )
            except Unauthorized as e:
                flash("Your login session has expired, please login again!", "danger")
                return redirect(url_for("login"))
        else:
            flash("You need to be logged in before you can access here!", "danger")
            return redirect(url_for("login"))
        return f(*args, **kwargs)

    return decorated

Теперь вы определили пользовательскую обертку. Вам нужно реализовать его на маршрутах, которые нуждаются в этом. Обновите свой auth_success маршрут с кодом ниже:

@app.route("/auth-success/")
@login_required
def auth_success():
    return "

Successfully authenticated account using Fauna!

"

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

Вы будете разрабатывать две (2) дополнительные веб -страницы для приложения. Они есть:

  • 2FA страница регистрации
  • 2fa -проверка страница

Шаг 1: Установка библиотеки PYOTP

В вашем терминале тип:

pip install pyotp

Шаг 2: Обновление старого потока аутентификации

Вам необходимо обновить предыдущий поток аутентификации, чтобы приспособить новое двухфакторное обновление аутентификации. При регистрации новой учетной записи пользователя вы будете генерировать токен SEED 2FA и перенаправить их, чтобы проверить их OTP перед панелью панели.

Во -первых, импортируйте библиотеку PYOTP в код приложения. Обновите app.py Импорт файлов с помощью кода ниже:

import pyotp

Затем обновите запрос фауны в регистр маршрут внутри app.py Файл с приведенным ниже кодом для создания токена семян 2FA вместе с профилем пользователя:

try:
    result = client.query(
        q.create(
            q.collection("users"), {
                "credentials": {"password": password},
                "data": {
                    "email": email,
                    "auth_enrolled": False,
                    "auth_secret": pyotp.random_base32()
                }
            }
        )
    )
except BadRequest as e:
    flash("The account you are trying to create already exists!", "danger")
    return redirect(url_for("register"))

auth_enrolled Параметр хранит, если текущий пользователь зарегистрирован или нет, в то время как auth_secret генерирует и проверяет токены 2FA.

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

session["user_secret"] = result["secret"]  
session["verified_2fa"] = False  
return redirect(url_for("verify_2fa"))

Вам также нужно обновить app.py Файл для реализации verify_2fa Маршрут приложение перенаправляет пользователя после успешной однофакторной аутентификации. Обновите app.py Файл с кодом ниже:

@app.route("/2fa/verify/")
@login_required
def verify_2fa():
    return "Verify 2FA Page!"

Далее вы будете внедрить несколько правил авторизации в приложении, например, предотвращение доступа к 2FA, которые не зарегистрировали 2FA, добраться до verify_2fa маршрут. Для этого вам нужна пользовательская обертка, которая обрабатывает этот процесс. Обновите app.py Файл с кодом ниже:

def get_user_details(user_secret):
    user_client = FaunaClient(secret=user_secret)
    user = user_client.query(
        q.current_identity()
    )
    user_details = client.query(
        q.get(
            q.ref(q.collection("users"), user.id())
        )
    )
    return user_details


def auth_enrolled(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        user_details = get_user_details(session["user_secret"])
        if not user_details["data"]["auth_enrolled"]:
            return redirect(url_for("enroll_2fa"))
        return f(*args, **kwargs)

    return decorated


def auth_not_enrolled(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        user_details = get_user_details(session["user_secret"])
        if user_details["data"]["auth_enrolled"]:
            return redirect(url_for("verify_2fa"))
        return f(*args, **kwargs)

    return decorated

Теперь вы определили пользовательскую обертку. Вам нужно реализовать его на маршрутах, которые нуждаются в этом. Обновите свой verify_2fa маршрут с кодом ниже:

@app.route("/2fa/verify/")
@login_required
@auth_enrolled
def verify_2fa():
    return "Verify 2FA Page!"


@app.route("/2fa/enroll/")
@login_required
@auth_not_enrolled
def enroll_2fa():
    return "Enroll 2FA Page!"

Шаг 3: Создание страницы регистрации 2FA

Страница регистрации 2FA – это то, где пользователям предоставляется свои секретные токены 2FA, которые будут зарегистрированы на их Authenticator App и протестировано в веб -приложении.

Вам нужно обновить reclly_2fa маршрут внутри app.py Файл для визуализации шаблона страницы регистрации; Обновите reclly_2fa маршрут с кодом ниже:

@app.route("/2fa/enroll/")
@login_required
@auth_not_enrolled
def enroll_2fa():
    user_details = get_user_details(session["user_secret"])
    secret_key = user_details["data"]["auth_secret"]

    return render_template("enroll_2fa.html", secret=secret_key)

Создайте другой файл с именем renll_2fa.html Это будет храниться в Шаблоны папка и сохранить в нем следующий код:

{% extends "bootstrap/base.html" %}

{% block content %}

Fauna Two-Factor Authentication (2FA) Demo

Set Up TOTP 2FA!
Instructions!
  • Download Google Authenticator on your mobile.
  • Create a new profile with the SECRET KEY below.
  • Submit the generated OTP in the form for authentication.
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} {% endfor %} {% endif %} {% endwith %}
{% endblock %}

Далее вы обновите reclly_2fa Маршрут для проверки отправленного токена 2FA и отметьте учетную запись пользователя как зарегистрированную, если проверка была успешной. Обновите app.py Файл с кодом ниже:

@app.route("/2fa/enroll/", methods=["GET", "POST"])
@login_required
@auth_not_enrolled
def enroll_2fa():
    user_details = get_user_details(session["user_secret"])
    secret_key = user_details["data"]["auth_secret"]

    if request.method == "POST":
        otp = int(request.form.get("otp"))

        if pyotp.TOTP(secret_key).verify(otp):
            user_details["data"]["auth_enrolled"] = True
            client.query(
                q.update(
                    q.ref(q.collection("users"), user_details["ref"].id()), {
                        "data": user_details["data"]
                    }
                )
            )
            flash("You have successfully enrolled 2FA for your profile, please authenticate yourself once more!", "success")
            return redirect(url_for("verify_2fa"))
        else:
            flash("The OTP provided is invalid, it has either expired or was generated using a wrong SECRET!", "danger")
            return redirect(url_for("enroll_2fa"))

    return render_template("enroll_2fa.html", secret=secret_key)

Шаг 4: Создание страницы проверки 2FA

Страница проверки 2FA – это то, где пользователи проверяют свой текущий сеанс входа в систему сразу после аутентификации с их паролем.

Вам нужно обновить verify_2fa маршрут внутри app.py Файл для визуализации шаблона страницы проверки; Обновите verify_2fa маршрут с кодом ниже:

@app.route("/2fa/verify/")
@login_required
def verify_2fa():
    return render_template("verify_2fa.html")

Создайте другой файл с именем Verify_2fa.html Это будет храниться в Шаблоны папка и сохранить в нем следующий код:

{% extends "bootstrap/base.html" %}

{% block content %}

Fauna Two-Factor Authentication (2FA) Demo

Set Up TOTP 2FA!
Instructions!
  • Download Google Authenticator on your mobile.
  • Enroll your account.
  • Submit the generated OTP in the form for authentication.
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} {% endfor %} {% endif %} {% endwith %}
Logout
{% endblock %}

Вам также нужно обновить app.py Файл для реализации Выход Маршрут ссылается на странице проверки 2FA. Обновите app.py Файл с кодом ниже:

@app.route("/logout/")
def logout():
    user_client = FaunaClient(secret=session["user_secret"])
    result = user_client.query(
        q.logout(True)
    )
    session.clear()
    return redirect(url_for("index"))

Далее вы обновите verify_2fa Маршрут, чтобы проверить представленный токен 2FA и завершить двухфакторную аутентификацию учетной записи пользователя. Обновите app.py Файл с кодом ниже:

@app.route("/2fa/verify/", methods=["GET", "POST"])
@login_required
@auth_enrolled
def verify_2fa():
    if request.method == "POST":
        otp = int(request.form.get("otp"))

        user_details = get_user_details(session["user_secret"])
        secret_key = user_details["data"]["auth_secret"]

        if pyotp.TOTP(secret_key).verify(otp):
            session["verify_2fa"] = True
            return redirect(url_for("auth_success"))
        else:
            flash("The OTP provided is invalid, it has either expired or was generated using a wrong SECRET!", "danger")
            return redirect(url_for("verify_2fa"))
    return render_template("verify_2fa.html")

Шаг 5: Реализация правил авторизации в колбе

Вы хотели бы сделать auth_success Маршрут доступен только пользователям, которые успешно аутентифицировали себя с помощью своего пароля и 2FA.

Для этого вам нужна пользовательская обертка, которая обрабатывает этот процесс. Обновите app.py Файл с кодом ниже:

def auth_verified(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get("verify_2fa"):
            return redirect(url_for("verify_2fa"))
        return f(*args, **kwargs)

    return decorated

Теперь вы определили пользовательскую обертку. Вам нужно реализовать его на маршрутах, которые нуждаются в этом. Обновите свой auth_success маршрут с кодом ниже:

@app.route("/auth-success/")
@login_required
@auth_verified
def auth_success():
    return "

Successfully authenticated account using Fauna and PyOTP!

"

В этой статье вы создали веб-приложение с Python и Flask, затем реализовали двухфакторную аутентификацию с использованием встроенных возможностей идентификации пользователей Fauna и управления сеансами и PYOTP для создания и проверки одноразовых паролей.

Хотите создать демонстрационное приложение дальше, посмотреть на пример кода или улучшить его функциональность? Посетите GitHub Repo . Я также создал Github Gist Это показывает возможности идентификации пользователей Fauna и управление сеансами с использованием Python. Если у вас есть какие -либо вопросы, не стесняйтесь обращаться ко мне в Twitter: @Lordghostx Анкет

Оригинал: “https://dev.to/lordghostx/implementing-two-factor-authentication-with-flask-pyotp-and-fauna-4jf3”