Как создать кнопку SSO — учебник по входу в Flask
Опубликовано: 2022-03-11Приложениям часто требуется функция входа в систему, чтобы пользователи могли сохранять данные, создавать свои собственные профили или, возможно, просто ограничивать доступ к конфиденциальным ресурсам. В современном приложении пользователи ожидают наличия стандартных функций входа в систему, таких как проверка электронной почты, сброс пароля или многофакторная аутентификация. Эти функции, хотя и необходимы, не так просто сделать правильно, и обычно они не являются основной задачей приложения.
Со стороны пользователя они могут не захотеть проходить длительный процесс регистрации, поскольку им нужно создать и запомнить еще одну пару электронной почты и пароля. Без надлежащего менеджера паролей пользователи, как правило, повторно используют один и тот же пароль, что ужасно с точки зрения безопасности.
Единый вход (SSO), в основном известный пользователям как вход с помощью кнопок социальных сетей , был изобретен как решение этой проблемы. Для пользователей было легко не проходить еще один болезненный процесс регистрации. Для бизнеса устранение трений для пользователей всегда является огромным выигрышем, а для разработчиков все функции, связанные с входом в систему, теперь делегированы поставщику удостоверений (Facebook, Google, Twitter и т. д.), что означает меньше кода! Ваше приложение просто доверяет поставщику удостоверений выполнять свою работу по проверке личности пользователя.
Система единого входа обычно работает на основе протокола OpenId Connect (OIDC) или SAML. SAML используется в основном в корпоративных приложениях. OIDC построен на основе OAuth2 и используется поставщиками социальных сетей, такими как Facebook, Google и т. д. В этом посте мы сосредоточимся на протоколе OIDC/OAuth2.
В этом руководстве по входу в Flask мы напишем пошаговое руководство по добавлению кнопки входа SSO в приложение Flask с SimpleLogin и Facebook в качестве поставщика удостоверений. Это можно сделать без использования какой-либо внешней библиотеки, но чтобы упростить тонкости OAuth, мы будем использовать Requests-OAuthlib, библиотеку для интеграции поставщиков OAuth. Если вы заинтересованы во внедрении системы единого входа с нуля, ознакомьтесь со статьей «Внедрение входа в систему единого входа — необработанный способ » .
В конце этой статьи у вас должно быть приложение Flask со следующими страницами:
- Домашняя страница с кнопками входа
- Страница информации о пользователе, где после успешного входа в систему пользователь сможет увидеть такую информацию, как имя, адрес электронной почты и аватар.
Весь код для этого руководства можно найти в репозитории flask-social-login-example.
Демо также доступно здесь. Не стесняйтесь ремиксовать код на Glitch.
Шаг 1: Приложение Bootstrap Flask
Установите flask
и Requests-OAuthlib
. Вы также можете использовать virtualenv
или pipenv
для изоляции среды.
pip установить колбу request_oauthlib
Создайте app.py
и маршрут, который отображает кнопку входа на главной странице:
import flask app = flask.Flask(__name__) @app.route("/") def index(): return """ <a href="/login">Login</a> """ if __name__ == '__main__': app.run(debug=True)
Давайте запустим это приложение и убедимся, что все работает хорошо:
python app.py
Вы должны увидеть эту страницу при открытии http://localhost:5000. Полный код находится на step1.py.
Шаг 2. Учетные данные поставщика удостоверений
В настоящее время существуют сотни (если не тысячи) поставщиков удостоверений, наиболее популярными из которых являются Facebook, Google, GitHub и Instagram. Для этого поста выбран SimpleLogin из-за его удобства для разработчиков. Однако тот же код будет работать с любым поставщиком удостоверений OAuth2. (Отказ от ответственности: я являюсь соучредителем SimpleLogin, что, кхм, могло быть фактором, повлиявшим на мое решение использовать его.)
Перейдите в SimpleLogin и создайте учетную запись, если у вас ее еще нет, а затем создайте новое приложение на вкладке «Разработчик».
На странице сведений о приложении скопируйте свой AppID и AppSecret и сохраните их в переменной среды. В терминологии OAuth клиент фактически означает стороннее приложение, т. е. ваше приложение. Мы можем поместить эти значения непосредственно в код, но рекомендуется сохранять учетные данные в переменных среды. Это также третий фактор в «Двенадцати факторах».
export CLIENT_ID={your AppID} export CLIENT_SECRET={your AppSecret}
В app.py
добавьте эти строки поверх файла, чтобы получить client id
client secret
.
import os CLIENT_ID = os.environ.get("CLIENT_ID") CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
Также добавьте эти URL-адреса OAuth поверх app.py
, которые будут использоваться на следующем шаге. Их также можно скопировать на странице конечных точек OAuth.
AUTHORIZATION_BASE_URL = "https://app.simplelogin.io/oauth2/authorize" TOKEN_URL = "https://app.simplelogin.io/oauth2/token" USERINFO_URL = "https://app.simplelogin.io/oauth2/userinfo"
Поскольку мы не хотим сейчас беспокоиться о настройке SSL, давайте скажем Requests-OAuthlib
, что можно использовать простой HTTP:
# This allows us to use a plain HTTP callback os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
Как обычно, код этого шага находится на step2.py.
Шаг 3: Перенаправление входа
Когда пользователь нажимает кнопку входа:
- Пользователь будет перенаправлен на страницу авторизации поставщика удостоверений с вопросом, хочет ли пользователь поделиться своей информацией с вашим приложением.
- После одобрения пользователя они будут перенаправлены обратно на страницу вашего приложения вместе с
code
в URL-адресе, который ваше приложение будет использовать для обмена наaccess token
, который позволит вам позже получить информацию о пользователе от поставщика услуг.
Поэтому нам нужны два маршрута: маршрут login
, который перенаправляет пользователя к поставщику удостоверений, и маршрут callback
, который получает code
и обменивает его на access token
. Маршрут обратного вызова также отвечает за отображение информации о пользователе.

@app.route("/login") def login(): simplelogin = requests_oauthlib.OAuth2Session( CLIENT_ID, redirect_uri="http://localhost:5000/callback" ) authorization_url, _ = simplelogin.authorization_url(AUTHORIZATION_BASE_URL) return flask.redirect(authorization_url) @app.route("/callback") def callback(): simplelogin = requests_oauthlib.OAuth2Session(CLIENT_ID) simplelogin.fetch_token( TOKEN_URL, client_secret=CLIENT_SECRET, authorization_response=flask.request.url ) user_info = simplelogin.get(USERINFO_URL).json() return f""" User information: <br> Name: {user_info["name"]} <br> Email: {user_info["email"]} <br> Avatar <img src="{user_info.get('avatar_url')}"> <br> <a href="/">Home</a> """
Нажатие на кнопку входа должно привести вас к следующему потоку. Полный код можно найти на GitHub по адресу step3.py.
Войти с Facebook
Настройка входа в Facebook, Google и Twitter немного сложна и требует дополнительных шагов, таких как настройка SSL или выбор правильных областей. Они выходят за рамки данной статьи.
Помимо сложного пользовательского интерфейса, самой сложной частью интеграции Facebook может быть поиск способа локального обслуживания вашего веб-приложения по HTTPS, поскольку новая версия Facebook SDK не поддерживает локальный простой HTTP. Я рекомендую использовать Ngrok, бесплатный инструмент для быстрого URL-адреса HTTPS.
Шаг 1: Создайте приложение Facebook
Перейдите на https://developers.facebook.com
и создайте новое приложение:
Затем выберите «Интегрировать вход через Facebook» на следующем экране:
Шаг 2. Учетные данные Facebook OAuth
Нажмите «Настройки/Основные» слева и скопируйте идентификатор приложения и секрет приложения . На самом деле это OAuth client-id
и client-secret
.
Обновите client-id
и client-secret
.
export FB_CLIENT_ID={your facebook AppId} export FB_CLIENT_SECRET={your facebook AppSecret}
Обновите AUTHORIZATION_BASE_URL и TOKEN_URL:
FB_AUTHORIZATION_BASE_URL = "https://www.facebook.com/dialog/oauth" FB_TOKEN_URL = "https://graph.facebook.com/oauth/access_token"
Домашняя страница:
@app.route("/") def index(): return """ <a href="/fb-login">Login with Facebook</a> """
Шаг 3: Конечные точки входа и обратного вызова
Если приложение обслуживается за ngrok
с помощью ngrok http 5000
, нам нужно установить текущий URL-адрес на URL-адрес ngrok.
# Your ngrok url, obtained after running "ngrok http 5000" URL = "https://abcdefgh.ngrok.io"
Убедитесь, что вы добавили URL-адрес в настройки входа/настройки Facebook, допустимые URI перенаправления OAuth:
Чтобы иметь доступ к электронной почте пользователя, вам необходимо добавить email
в scope
:
FB_SCOPE = ["email"] @app.route("/fb-login") def login(): facebook = requests_oauthlib.OAuth2Session( FB_CLIENT_ID, redirect_uri=URL + "/fb-callback", scope=FB_SCOPE ) authorization_url, _ = facebook.authorization_url(FB_AUTHORIZATION_BASE_URL) return flask.redirect(authorization_url)
Маршрут callback
немного сложнее, так как Facebook требует исправления соответствия:
from requests_oauthlib.compliance_fixes import facebook_compliance_fix @app.route("/fb-callback") def callback(): facebook = requests_oauthlib.OAuth2Session( FB_CLIENT_ID, scope=FB_SCOPE, redirect_uri=URL + "/fb-callback" ) # we need to apply a fix for Facebook here facebook = facebook_compliance_fix(facebook) facebook.fetch_token( FB_TOKEN_URL, client_secret=FB_CLIENT_SECRET, authorization_response=flask.request.url, ) # Fetch a protected resource, ie user profile, via Graph API facebook_user_data = facebook.get( "https://graph.facebook.com/me?fields=id,name,email,picture{url}" ).json() email = facebook_user_data["email"] name = facebook_user_data["name"] picture_url = facebook_user_data.get("picture", {}).get("data", {}).get("url") return f""" User information: <br> Name: {name} <br> Email: {email} <br> Avatar <img src="{picture_url}"> <br> <a href="/">Home</a> """
Теперь, нажав «Войти через Facebook», вы сможете пройти весь процесс.
Полный код находится на facebook.py.
Заключение
Поздравляем — вы успешно интегрировали SSO-вход в приложение Flask!
Для простоты в этом руководстве не упоминаются другие концепции OAuth, такие как область действия и состояние, которые важны для защиты от атак с подделкой межсайтовых запросов. Вам также, вероятно, потребуется хранить информацию о пользователе в базе данных, которая не рассматривается в этой статье.
Приложение также должно обслуживаться по протоколу https в рабочей среде, что сегодня можно легко сделать с помощью Let’s Encrypt.
Удачного авторизации!