2025, Nov 17 00:01

Flet 0.21.0 и Discord OAuth: почему не срабатывает on_login и что делать

Проблема Discord OAuth в Flet 0.21.0: on_login не вызывается из‑за нового эндпоинта /oauth_callback. Как настроить redirect_url, чтобы авторизация заработала.

При интеграции Discord OAuth в приложение на Flet всё может выглядеть корректно: появляется кнопка входа, браузер запрашивает авторизацию, а URL перенаправления возвращает на ваш localhost. Однако обработчик on_login так и не срабатывает. Причина неброская, но простая: в Flet 0.21.0 изменился эндпоинт обратного вызова OAuth.

Демонстрация проблемы

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

import os
import flet
from flet import ElevatedButton, Page
from flet.auth import OAuthProvider

def app_entry(screen: Page):
    discord_auth = OAuthProvider(
        client_id=os.getenv("DISCORD_CLIENT_ID"),
        client_secret=os.getenv("DISCORD_CLIENT_SECRET"),
        authorization_endpoint="https://discord.com/oauth2/authorize",
        token_endpoint="https://discord.com/api/oauth2/token",
        scopes=["identify","guilds","email","guilds.join","guilds.members.read"],
        redirect_url="http://localhost:2000/api/auth/discord/redirect",
    )

    def handle_signin(evt):
        screen.login(discord_auth)
        print("hello")

    def after_login(evt):
        screen.add(flet.Text("on_logi called"))
        print("on_logi called", flush=True)
        if evt.error:
            screen.add(ElevatedButton(f"Login error: {evt.error}"))
            return
        screen.add(ElevatedButton(f"User ID: {screen.auth.user.id}"))
        screen.add(ElevatedButton(f"Access token: {screen.auth.token.access_token}"))
        screen.add(flet.Text("HELLOO DID IT WORK?"))

    screen.on_login = after_login
    screen.add(ElevatedButton("Login with Discord", on_click=handle_signin))

flet.app(app_entry, port=2000, view=flet.WEB_BROWSER)

Что происходит на самом деле и почему

Начиная с Flet 0.21.0, из‑за перехода веб‑сервера на FastAPI URL‑эндпоинт обработчика OAuth изменился с /api/oauth/redirect на /oauth_callback. Если ваш redirect_url (и Redirect URI в настройках приложения Discord) указывает на другой путь, фреймворк не попадёт во внутренний обработчик, который триггерит page.on_login, поэтому ваш колбэк не запустится.

Решение

Направьте перенаправление на новый эндпоинт. Используйте /oauth_callback в качестве адреса возврата OAuth. Если нужен другой путь, его можно переопределить переменной окружения FLET_OAUTH_CALLBACK_HANDLER_ENDPOINT.

import os
import flet
from flet import ElevatedButton, Page
from flet.auth import OAuthProvider

def app_entry(screen: Page):
    discord_auth = OAuthProvider(
        client_id=os.getenv("DISCORD_CLIENT_ID"),
        client_secret=os.getenv("DISCORD_CLIENT_SECRET"),
        authorization_endpoint="https://discord.com/oauth2/authorize",
        token_endpoint="https://discord.com/api/oauth2/token",
        scopes=["identify","guilds","email","guilds.join","guilds.members.read"],
        redirect_url="http://localhost:2000/oauth_callback",
    )

    def handle_signin(evt):
        screen.login(discord_auth)
        print("hello")

    def after_login(evt):
        screen.add(flet.Text("on_logi called"))
        print("on_logi called", flush=True)
        if evt.error:
            screen.add(ElevatedButton(f"Login error: {evt.error}"))
            return
        screen.add(ElevatedButton(f"User ID: {screen.auth.user.id}"))
        screen.add(ElevatedButton(f"Access token: {screen.auth.token.access_token}"))
        screen.add(flet.Text("HELLOO DID IT WORK?"))

    screen.on_login = after_login
    screen.add(ElevatedButton("Login with Discord", on_click=handle_signin))

flet.app(app_entry, port=2000, view=flet.WEB_BROWSER)

Ссылка: из обсуждений на GitHub — Flet Authentication providers problem · flet-dev/flet · Discussion #2950.

Почему это важно

Потоки OAuth крайне чувствительны к URI перенаправления. Несоответствие между тем, что использует провайдер идентификации, и тем, чего ждёт ваше приложение, обычно приводит к «тихим» сбоям: в браузере всё завершается, но приложение не получает токен и не вызывает хук входа. Зная точный эндпоинт, который использует фреймворк, вы избегаете часов отладки вкладок и серверных логов.

Что важно запомнить

Для Flet 0.21.0 и новее убедитесь, что и в настройках приложения Discord, и в вашем коде для перенаправления используется /oauth_callback. Если развёртыванию нужен свой путь, задайте его через переменную окружения FLET_OAUTH_CALLBACK_HANDLER_ENDPOINT. Достаточно согласовать эти значения — и on_login снова начнёт выполняться, а в приложении появится доступ к аутентифицированному пользователю и токену.