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

Добавление аутентификации Okta в существующее веб-приложение Flask

Узнайте, как добавить Okta для аутентификации пользователей в существующее веб-приложение Flask.

Автор оригинала: Matt Makai.

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

Библиотеки

Для этого урока требуется Python 3, и мы будем также используйте:

Весь готовый код в этом сообщении в блоге предоставляется с открытым исходным кодом. под лицензией MIT на GitHub под auth-existing-flask-app/finished каталог примеров кода блога репозиторий. Используйте и злоупотребляйте исходным кодом для своих собственных приложений.

Установка зависимостей

Мы начнем с существующего веб-приложения Flask. Если вы этого не сделаете иметь свой собственный, который вы изменяете, клонируйте этот репозиторий Git:

git clone [email protected]:fullstackpython/blog-code-examples.git

Затем создайте новый Python virtualenv для этого проекта:

python3 -m venv flaskauth

Активируйте виртуальную среду с помощью скрипта activate :

. ./flaskauth/bin/activate

Командная строка должна измениться после активации:

Активация виртуального flaskauth.

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

Перейдите в каталог проекта в block-code-examples Git репозиторий, который вы клонировали.

cd blog-code-examples/auth-existing-flask-app/start/

Теперь мы можем установить зависимости для существующего проекта.

pip install -r requirements.txt

Найдите вывод, аналогичный приведенному ниже, чтобы убедиться, что зависимости Успешно установлен:

...
Collecting amqp<3.0,>=2.1.4 (from kombu<5.0,>=4.0.2->Celery==4.1.0->-r requirements.txt (line 4))
  Downloading https://files.pythonhosted.org/packages/7f/cf/12d4611fc67babd4ae250c9e8249c5650ae1933395488e9e7e3562b4ff24/amqp-2.3.2-py2.py3-none-any.whl (48kB)
    100% |████████████████████████████████| 51kB 10.7MB/s 
Collecting six>=1.5 (from python-dateutil->alembic>=0.6->Flask-Migrate==2.2.0->-r requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl
Collecting vine>=1.1.3 (from amqp<3.0,>=2.1.4->kombu<5.0,>=4.0.2->Celery==4.1.0->-r requirements.txt (line 4))
  Downloading https://files.pythonhosted.org/packages/10/50/5b1ebe42843c19f35edb15022ecae339fbec6db5b241a7a13c924dabf2a3/vine-1.1.4-py2.py3-none-any.whl
Installing collected packages: click, itsdangerous, Werkzeug, MarkupSafe, Jinja2, Flask, SQLAlchemy, Flask-SQLAlchemy, Mako, python-editor, six, python-dateutil, alembic, Flask-Migrate, billiard, pytz, vine, amqp, kombu, Celery, redis, WTForms
  Running setup.py install for MarkupSafe ... done
  Running setup.py install for SQLAlchemy ... done
  Running setup.py install for Mako ... done
  Running setup.py install for python-editor ... done
  Running setup.py install for alembic ... done
  Running setup.py install for billiard ... done
  Running setup.py install for WTForms ... done
Successfully installed Celery-4.1.0 Flask-1.0.2 Flask-Migrate-2.2.0 Flask-SQLAlchemy-2.3.2 Jinja2-2.10 Mako-1.0.7 MarkupSafe-1.0 SQLAlchemy-1.2.12 WTForms-2.1 Werkzeug-0.14.1 alembic-1.0.1 amqp-2.3.2 billiard-3.5.0.4 click-7.0 itsdangerous-1.1.0 kombu-4.2.1 python-dateutil-2.7.5 python-editor-1.0.3 pytz-2018.7 redis-2.10.6 six-1.11.0 vine-1.1.4

Нам нужна пара дополнительных зависимостей для нашего проекта, чтобы работа, flask-oidc и okta :

pip install flask-oidc>=1.4.0 okta==0.0.4

Теперь зависимости правильно установлены в нашей виртуальной среде. Давайте протестируем приложение, чтобы убедиться, что оно работает должным образом.

export FLASK_APP=flaskdash.py
export FLASK_ENV=development
flask run

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

* Serving Flask app "flaskdash.py" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 203-814-092

Перейдите на localhost: 5000 в своем браузере, и мы должны увидеть панель незавершенного производства:

Панель инструментов существующего приложения Flask.

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

Okta для аутентификации

Перейдите на страницу регистрации разработчиков Okta .

Целевая страница разработчиков Okta для регистрации.

Зарегистрируйте новую учетную запись или войдите в существующую.

Процесс регистрации разработчиков Okta.

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

Электронная почта подписки на Okta.

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

Okta завершить создание учетной записи.

Нажмите кнопку «Создать учетную запись», и вы перейдете к Панель разработчика Okta.

Панель разработчика Okta.

Найдите «URL-адрес организации», как показано на следующем рисунке.

Значение URL-адреса Okta Org.

Мы собираемся использовать этот URL в нашем секретном файле учетных данных, чтобы наше веб-приложение Flask может правильно подключаться к службе Okta.

Создайте новый файл в каталоге вашего проекта с именем openidconnect_secrets.json со следующим содержимым:

{
  "web": {
    "client_id": "{{ OKTA_CLIENT_ID }}",
    "client_secret": "{{ OKTA_CLIENT_SECRET }}",
    "auth_uri": "{{ OKTA_ORG_URL }}/oauth2/default/v1/authorize",
    "token_uri": "{{ OKTA_ORG_URL }}/oauth2/default/v1/token",
    "issuer": "{{ OKTA_ORG_URL }}/oauth2/default",
    "userinfo_uri": "{{ OKTA_ORG_URL }}/oauth2/default/userinfo",
    "redirect_uris": [
      "http://localhost:5000/oidc/callback"
    ]
  }
}

Замените четыре заполнителя {{OKTA_ORG_URL}} значением URL организации. найдено в вашей панели управления. Мы заполним остальные заполнители с помощью фактические значения по мере прохождения обучения. Мой Файл openidconnect_secret.json в настоящее время будет иметь следующие значения основаны на моем URL-адресе организации панели разработчика. Помните, что значения ваших URL будут другими!

{
  "web": {
    "client_id": "{{ OKTA_CLIENT_ID }}",
    "client_secret": "{{ OKTA_CLIENT_SECRET }}",
    "auth_uri": "https://dev-860408.oktapreview.com/oauth2/default/v1/authorize",
    "token_uri": "https://dev-860408.oktapreview.com/oauth2/default/v1/token",
    "issuer": "https://dev-860408.oktapreview.com/oauth2/default",
    "userinfo_uri": "https://dev-860408.oktapreview.com/oauth2/default/userinfo",
    "redirect_uris": [
      "http://localhost:5000/oidc/callback"
    ]
  }
}

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

Обновление приложения Flask с помощью Okta

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

Обновите config.py код Flask, указав следующие выделенные строки.

import os


class Config(object):
    SECRET_KEY = os.getenv('SECRET_KEY') or 'development key'

    # Redis
    REDIS_SERVER = os.getenv('REDIS_SERVER') or 'localhost'
    REDIS_PORT = os.getenv('REDIS_PORT') or 6379
    REDIS_DB = os.getenv('REDIS_DB') or 1
    REDIS_URL = 'redis://{}:{}'.format(REDIS_SERVER, REDIS_PORT)

    # Celery task queue
    CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL') or REDIS_URL
    CELERY_RESULT_BACKEND = os.getenv('CELERY_RESULT_BACKEND') or REDIS_URL

    # database settings
    SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') or \
      'sqlite:///' + os.path.join(os.path.abspath(os.path.dirname(__file__)),
      'flaskdash.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

    OIDC_CLIENT_SECRETS = "openidconnect_secrets.json"
    OIDC_COOKIE_SECURE = False
    OIDC_CALLBACK_ROUTE = "/oidc/callback"
    OIDC_SCOPES = ["openid", "email", "profile"]
    OIDC_ID_TOKEN_COOKIE_NAME = "oidc_token"

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

Остальной новый код задает конфигурацию приложения Flask. значения, которые можно использовать для создания экземпляров OpenID Connect и Клиенты Okta.

  • OIDC_CLIENT_SECRETS : расположение файла секретов OpenID Connect.
  • OIDC_COOKIE_SECURE : разрешает режим разработки для тестирования входа пользователя и
  • регистрация без SSL. Ваше приложение должно установить для него значение True в
  • производственное приложение.
  • OIDC_CALLBACK_ROUTE : URL-адрес в веб-приложении для обработки логинов пользователей.
  • OIDC_SCOPES : какие данные запрашивать о пользователе при входе в систему. Наши
  • приложение запрашивает основную информацию об электронной почте, имени и профиле
  • SECRET_KEY : это параметр Flask для обеспечения безопасности сеансов. Ключ
  • никогда не должны публиковаться, иначе пользовательские сеансы вашего веб-приложения будут
  • скомпрометирован.

Но где мы можем взять эти значения конфигурации приложения? Мы необходимо получить их из нашей учетной записи Okta, так что вернитесь на панель инструментов для создания нового приложения OpenID Connect.

Выберите приложения на панели инструментов разработчика Okta.

Приложения OpenID Connect используют идентификатор клиента и секрет клиента в место традиционных логинов и паролей. Идентификатор клиента и секрет клиента скажет вашему серверу авторизации распознать ваш применение. Нажмите кнопку «Добавить приложение».

Нажмите кнопку «Добавить приложение».

На экране нового приложения выберите «Интернет» и нажмите «Далее».

Выберите веб-приложение.

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

Установить значения конфигурации приложения.

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

На следующей странице прокрутите вниз, чтобы найти своего клиента и секретные ключи.

Сохраните учетные данные клиента для дальнейшего использования.

Скопируйте и вставьте идентификатор клиента и секрет клиента в следующий выделенные строки для замены {{OKTA_CLIENT_ID}} и {{OKTA_CLIENT_SECRET}} заполнители.

{
  "web": {
    "client_id": "{{ OKTA_CLIENT_ID }}",
    "client_secret": "{{ OKTA_CLIENT_SECRET }}",
    "auth_uri": "https://dev-860408.oktapreview.com/oauth2/default/v1/authorize",
    "token_uri": "https://dev-860408.oktapreview.com/oauth2/default/v1/token",
    "issuer": "https://dev-860408.oktapreview.com/oauth2/default",
    "userinfo_uri": "https://dev-860408.oktapreview.com/oauth2/default/userinfo",
    "redirect_uris": [
      "http://localhost:5000/oidc/callback"
    ]
  }
}

Сохраните файл и убедитесь, что он не контролируется версиями, поскольку секретные ценности должны оставаться в секрете.

Перед обновлением у нас есть еще один шаг на панели инструментов разработчика Okta наше приложение Flask с кодом аутентификации: создание токен аутентификации API . Перейдите на вкладку API.

Щелкните вкладку API на панели управления.

Нажмите кнопку «Создать токен».

Создайте токен аутентификации для доступа к Okta.

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

Хорошо, наконец-то у нас есть вся конфигурация сервиса Okta и токены в наш файл openidconnect_secret.json , который нам нужен для завершения нашего приложения.

Обновите app/__ init__.py этими выделенными строками:

import redis
from os import environ
from flask import Flask
from app.utils import make_celery
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_oidc import OpenIDConnect
from okta import UsersClient


app = Flask(__name__, static_url_path='/static')
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db) 

# connect to Redis instance
redis_db = redis.StrictRedis(host=app.config['REDIS_SERVER'],
                             port=app.config['REDIS_PORT'],
                             db=app.config['REDIS_DB'])
celery = make_celery(app)


# instantiate OpenID client to handle user session
oidc = OpenIDConnect(app)
# Okta client will determine if a user has an appropriate account
okta_client = UsersClient(environ.get("OKTA_ORG_URL"),
                          environ.get("OKTA_AUTH_TOKEN"))


from app import routes

Теперь мы можем получить доступ к okta_client в наших маршрутах. Откройте app/routes.py и обновите следующие строки:

from flask import send_from_directory, render_template
from flask import redirect, g
from app import app, oidc, okta_client


@app.before_request
def before_request():
    if oidc.user_loggedin:
        g.user = okta_client.get_user(oidc.user_getfield("sub"))
    else:
        g.user = None


@app.route('/js/')
def send_js(path):
    return send_from_directory('js', path)


@app.route('/css/')
def send_css(path):
    return send_from_directory('css', path)


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


@app.route("/repositories")
@oidc.require_login
def repositories():
    return render_template('repositories.html')


@app.route("/login")
@oidc.require_login
def login():
    return redirect(url_for(".repositories"))


@app.route("/logout")
def logout():
    oidc.logout()
    return redirect(url_for(".landing_page"))

Вышеупомянутые новые выделенные строки проверяют, вошел ли пользователь в систему. перед каждым запросом. Если для маршрута требуется авторизованный пользователь из-за декоратор @ oidc.require_login , тогда пользователь будет перенаправлен на войдите на страницу. Мы также добавили маршруты в разделах /login и /logout , чтобы можно войти и выйти из приложения.

Задайте три переменные среды, чтобы наше приложение могло использовать их, когда мы запустить его. Убедитесь, что заполнители ORG_URL и AUTH_TOKEN установлены с ваше фактическое значение URL-адреса организации и токен аутентификации на панели инструментов разработчика Okta.

В командной строке выполните следующие команды, не забудьте заменить любые значения-заполнители с вашими собственными токенами и URL-адресами:

# this tells Flask we want to run the built-in server in dev mode
export FLASK_ENV=development
# make sure to use a very long random string here that cannot be guessed
export SECRET_KEY='a very long string with lots of numbers and letters'
# this is the same Org URL found on your developer dashboard
# for example, https://dev-860408.oktapreview.com
export OKTA_ORG_URL='ORG_URL'
# this is the API authentication token we created
export OKTA_AUTH_TOKEN='AUTH_TOKEN'

Теперь перезапустите приложение Flask:

set FLASK_APP=app.py
flask run

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

(flaskauth)$ flask run
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 415-920-546

Направляйтесь на localhost: 5000 в браузере, в который вы еще не вошли. ваша учетная запись Okta (отлично работает окно в режиме инкогнито вашего веб-браузера).

Панель управления в режиме инкогнито.

Давайте протестируем функцию перенаправления, когда мы попытаемся перейти на /панель управления маршрут, перейдя на localhost: 5000/repositories. Мы перенаправляемся на Okta страница авторизации.

Перенаправление в режиме инкогнито.

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

Попал на страницу репозиториев после входа в систему.

Чтобы не аутентифицировать пользователя, перейдите по адресу localhost: 5000/logout. Когда ты вернешься to localhost: 5000/repositories снова вам нужно будет повторно пройти аутентификацию.

Что теперь?

Мы настроили существующее приложение Flask для использования Okta для аутентификация пользователей и управление идентификацией через Okta API .

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

  • Как добавить размещенный мониторинг в веб-приложения Flask
  • Разработка и запуск приложений Flask в контейнерах Docker
  • Ответ на текстовые SMS-сообщения с помощью Python и Flask

Вы также можете определить, что кодировать дальше в своем проекте Python, прочитав страница содержания Full Stack Python.

Вопросов? Свяжитесь со мной через Twitter @fullstackpython или @mattmakai . Я также на GitHub с имя пользователя mattmakai .

Что-то не так с этим сообщением? Вилка исходный код этой страницы на GitHub и отправьте запрос на перенос.