Как в Python-приложении добавить поддержку кастомного OAuth 2.0 провайдера

Ответ

Для интеграции кастомного OAuth 2.0 провайдера в Python-приложении обычно используются специализированные библиотеки, такие как authlib или requests-oauthlib. Они абстрагируют сложность протокола и предоставляют удобный API.

Процесс сводится к регистрации нового провайдера с указанием его уникальных эндпоинтов и учетных данных (client_id, client_secret).

Пример с использованием authlib и Flask:

from flask import Flask, url_for
from authlib.integrations.flask_client import OAuth

app = Flask(__name__)
# ...нужна конфигурация app.secret_key

oauth = OAuth(app)

# Регистрация кастомного OAuth 2.0 провайдера
oauth.register(
    name='my_custom_provider', # Уникальное имя для вашего приложения
    client_id='your-client-id-from-provider',
    client_secret='your-client-secret-from-provider',
    authorize_url='https://custom-provider.com/oauth/authorize',
    access_token_url='https://custom-provider.com/oauth/token',
    api_base_url='https://api.custom-provider.com/v1/',
    client_kwargs={'scope': 'read_profile openid'}
)

@app.route('/login')
def login():
    # Перенаправляем пользователя на страницу авторизации провайдера
    redirect_uri = url_for('authorize', _external=True)
    return oauth.my_custom_provider.authorize_redirect(redirect_uri)

@app.route('/authorize')
def authorize():
    # Получаем токен доступа после успешной авторизации
    token = oauth.my_custom_provider.authorize_access_token()
    # Здесь можно получить данные пользователя, используя токен
    # user_info = oauth.my_custom_provider.get('userinfo', token=token)
    return f"Access Token: {token['access_token']}"

Ключевые шаги:

  1. Регистрация провайдера: С помощью oauth.register() определяется новый сервис.
  2. Конфигурация URL: Указываются эндпоинты: authorize_url (куда перенаправлять пользователя), access_token_url (для обмена кода авторизации на токен) и api_base_url (для запросов к API).
  3. Учетные данные: client_id и client_secret получаются при регистрации вашего приложения на стороне OAuth-провайдера.
  4. Инициация авторизации: Метод authorize_redirect() запускает процесс, перенаправляя пользователя на страницу входа провайдера.

Ответ 18+ 🔞

Да ты посмотри, какая хуйня! Вроде бы OAuth 2.0, стандарт, протокол, всё такое. А на деле — один сплошной цирк с конями, если вручную всё это городить. Ну, блядь, нахуя? Для этого и придумали библиотеки, чтобы не ебаться с этой всей рутиной.

Вот смотри, возьмём, к примеру, authlib. Библиотека, внатуре, годная. Она как раз для таких распиздяев, как мы с тобой, которые не хотят вникать в каждую строчку RFC.

Весь процесс, по сути, сводится к тому, чтобы твоё приложение сказало: «Эй, провайдер, я вот такой-то, вот мой client_id и client_secret, дай-ка мне доступ к этому пользователю». А провайдер такой: «Ага, щас, пользователь подтвердит — и будет тебе счастье в виде токена».

Вот тебе живой пример на Flask, чтобы было понятно, как эта мартышлюшка работает:

from flask import Flask, url_for
from authlib.integrations.flask_client import OAuth

app = Flask(__name__)
# ...нужно не забыть про app.secret_key, а то вся авторизация накроется медным тазом

oauth = OAuth(app)

# Вот тут и происходит вся магия регистрации твоего кастомного провайдера
# Представь, что ты записываешь нового участника в свою шайку
oauth.register(
    name='my_custom_provider', # Уникальная кличка для твоего провайдера внутри приложения
    client_id='your-client-id-from-provider',   # Твой пропуск, который выдали на стороне
    client_secret='your-client-secret-from-provider', # Твой секретный пароль, который НИКОМУ НЕ ПОКАЗЫВАЙ, блядь!
    authorize_url='https://custom-provider.com/oauth/authorize', # Адрес, куда гнать пользователя логиниться
    access_token_url='https://custom-provider.com/oauth/token',  # Адрес, куда ползти выпрашивать токен
    api_base_url='https://api.custom-provider.com/v1/', # Базовый адрес, чтобы потом данные пользователя стянуть
    client_kwargs={'scope': 'read_profile openid'} # А это список того, на что мы, собственно, претендуем
)

@app.route('/login')
def login():
    # Тыкаем пользователя кнопкой и отправляем его в увлекательное путешествие к провайдеру
    redirect_uri = url_for('authorize', _external=True)
    return oauth.my_custom_provider.authorize_redirect(redirect_uri)

@app.route('/authorize')
def authorize():
    # Пользователь вернулся, и если всё ок — у нас в кармане токен!
    token = oauth.my_custom_provider.authorize_access_token()
    # А вот тут уже можно, ебать, праздновать и тащить данные пользователя
    # user_info = oauth.my_custom_provider.get('userinfo', token=token)
    return f"Access Token: {token['access_token']}" # Смотри-ка, а он и правда есть!

Если разложить по полочкам, то получается:

  1. Регистрация провайдера (oauth.register): Ты, сука, знакомишь свою библиотеку с новым сервисом. Говоришь: «Запомни, этот чувак так-то выглядит, вот его адреса, вот мои с ним секретные слова».
  2. Конфигурация URL: Самое важное — не перепутать, блядь, адреса. authorize_url — это дверь, в которую стучится пользователь. access_token_url — это чёрный ход, куда твоё приложение ползёт за заслуженной наградой.
  3. Учетные данные: client_id и client_secret — это как паспорт и виза. Без них тебя, мудя, на порог не пустят. Получаешь их, когда регистрируешь своё приложение у самого OAuth-провайдера.
  4. Старт авторизации (authorize_redirect): Ты делаешь вид, что показываешь пользователю красивую кнопку «Войти через...», а на самом деле просто даёшь ему пинка под зад, чтобы он пошёл авторизовываться куда надо.

И всё, ёпта! Библиотека сама сгенерирует нужные запросы, сама разберёт ответы, сама вытащит токен из всех этих JSON-ов. Тебе остаётся только этот токен грамотно применить. Красота, а не жизнь!