Flet Auth0OAuthProvider 接入指南:用 Python 为 Flet 应用集成 Auth0 OAuth 登录
【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet
flet.auth.Auth0OAuthProvider是 Flet Python SDK 内置的 OAuth 提供商预设类,专门用于将 Auth0 身份平台接入 Flet 应用。它封装了 Auth0 的授权端点、令牌端点与/userinfo用户信息获取逻辑,开发者只需提供 Auth0 租户域名与应用程序凭据,即可通过page.login()完成标准的授权码(Authorization Code)登录流程。读完本文,你将掌握 Auth0OAuthProvider 的全部构造参数与默认配置、与page.login()配合的完整接入步骤,以及底层令牌交换、用户资料加载与令牌刷新的实现原理。
Auth0OAuthProvider 是什么
在 Flet 的认证体系中,Auth0OAuthProvider是OAuthProvider基类的一个"预设(preset)"实现,其源码位于 sdk/python/packages/flet/src/flet/auth/providers/auth0_oauth_provider.py。所谓预设,是指它把 Auth0 特有的一整套 OAuth 端点、作用域与用户 ID 提取规则预先配置好,让开发者免去手工拼接端点 URL 的繁琐工作。
该类在 flet/auth/init.py 中被公开导出,并通过惰性导入(__getattr__)按需加载,因此标准导入方式是:
from flet.auth import Auth0OAuthProvider它与AzureOAuthProvider、GitHubOAuthProvider、GoogleOAuthProvider一起并列于 providers 目录,共享同一个OAuthProvider基类抽象。
构造函数与参数详解
Auth0OAuthProvider的构造函数定义如下(引用自源码 docstring):
Auth0OAuthProvider( domain: str, # Auth0 租户域名(不带协议),例如 example.us.auth0.com client_id: str, # Auth0 应用客户端 ID client_secret: str, # Auth0 应用客户端密钥 redirect_url: str, # 注册在 Auth0 中的回调/重定向地址 audience: Optional[str] = None, # 可选的 API 标识符 )| 参数 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
domain | str | 必填 | Auth0 租户域名,不带协议前缀,例如example.us.auth0.com。该值将用于拼接全部端点 URL |
client_id | str | 必填 | Auth0 Application 的 Client ID,在 Auth0 控制台创建应用后获得 |
client_secret | str | 必填 | Auth0 Application 的 Client Secret,用于令牌端点换取令牌 |
redirect_url | str | 必填 | 回调地址,必须与 Auth0 控制台 Allowed Callback URLs 中注册的地址完全一致 |
audience | str | 可选 | Auth0 API Identifier(API 标识符)。传入后将以audience查询参数附加到授权 URL,用于申请面向特定 API 资源服务器的访问令牌;不传则忽略 |
从源码结构看,domain与audience在super().__init__()调用完成后还会被保存为实例属性(self.domain、self.audience),供后续使用或调试查看。
预置的端点与作用域配置
Auth0OAuthProvider的核心价值在于将 Auth0 的协议细节固化到基类构造参数中。以下映射均可在源码第 42-56 行直接验证:
| 基类参数 | Auth0OAuthProvider 预置值 |
|---|---|
authorization_endpoint | https://{domain}/authorize |
token_endpoint | https://{domain}/oauth/token |
user_endpoint | https://{domain}/userinfo |
scopes | ["offline_access"] |
user_scopes | ["openid", "profile", "email"] |
group_scopes | [](Auth0 预设不加载分组) |
user_id_fn | lambda u: u["sub"](取/userinfo响应中的sub声明作为用户 ID) |
authorization_params | {"audience": audience}(仅当传入audience时) |
几个关键设计值得注意:
offline_access作用域:作为基础作用域总是被请求,它让 Auth0 返回refresh_token,从而支持令牌自动刷新(见下文"令牌刷新"一节)。openid/profile/email:作为user_scopes,仅在fetch_user=True时被合并进最终请求的作用域列表。user_id_fn使用sub声明:sub是 Auth0 ID Token 与/userinfo响应中的稳定用户标识,Flet 用它构造User.id。
OAuthProvider基类(oauth_provider.py)还支持code_challenge、code_challenge_method、code_verifier三个 PKCE 参数以及authorization_params扩展参数,Auth0 预设未显式设置 PKCE 字段,如需使用可在继承类中补充。
在 Auth0 控制台与 Flet 应用中完成接入
第 1 步:Auth0 侧准备
- 登录 Auth0 控制台,创建一个 Application(类型选择 Regular Web Application 或 Native,视你的 Flet 运行形态而定)。
- 记录该应用的Client ID与Client Secret。
- 在应用设置的Allowed Callback URLs中注册回调地址。Flet 文档中常见的本地回调地址为
http://localhost:8550/oauth_callback(见 website/docs/cookbook/authentication.md 中的示例约定),你也可以使用自己的地址,但必须与代码中的redirect_url完全一致。 - 如需调用受保护 API,可在 APIs 中创建 API 并记录其Identifier,作为
audience参数。
第 2 步:构造 Provider 并调用 page.login()
以下代码演示了最小可用接入。page.login()的完整签名位于 page.py:
import os import flet as ft from flet.auth import Auth0OAuthProvider AUTH0_DOMAIN = os.getenv("AUTH0_DOMAIN", "example.us.auth0.com") AUTH0_CLIENT_ID = os.getenv("AUTH0_CLIENT_ID") AUTH0_CLIENT_SECRET = os.getenv("AUTH0_CLIENT_SECRET") AUTH0_AUDIENCE = os.getenv("AUTH0_AUDIENCE") # 可选 provider = Auth0OAuthProvider( domain=AUTH0_DOMAIN, client_id=AUTH0_CLIENT_ID, client_secret=AUTH0_CLIENT_SECRET, redirect_url="http://localhost:8550/oauth_callback", audience=AUTH0_AUDIENCE, # 可选:请求面向特定 API 的访问令牌 ) def main(page: ft.Page): def on_login(e): if e.error: print("登录失败:", e.error, e.error_description) else: # e 为 LoginEvent;user 为 flet.auth.User 实例 user = page.auth.user if hasattr(page, "auth") else None print("登录成功:", user.id if user else "unknown") page.on_login = on_login async def login_click(e): # 返回 AuthorizationService 实例,其 .user 属性保存登录用户 await page.login(provider, fetch_user=True) page.add(ft.ElevatedButton("使用 Auth0 登录", on_click=login_click)) ft.app(main, port=8550)page.login()的关键参数与默认值:
| 参数 | 默认值 | 说明 |
|---|---|---|
provider | 无 | 传入Auth0OAuthProvider实例 |
fetch_user | True | 是否在登录后从/userinfo拉取用户资料 |
fetch_groups | False | 是否加载用户分组(Auth0 预设的group_scopes为空) |
scope | None | 额外的初始 OAuth 作用域,会与预设作用域合并去重 |
saved_token | None | 传入之前持久化的令牌 JSON 字符串可跳过交互式登录,直接恢复会话 |
redirect_to_page | False | Web 应用在同一浏览器标签打开授权页时使用 |
运行形态差异:在 Web 形态下,Flet 通过UrlLauncher().open_window(authorization_url, title="flet_oauth_signin")打开授权窗口;在桌面端则调用UrlLauncher().launch_url()拉起系统浏览器。回调完成后,_authorize_callback()会校验state、关闭内嵌 WebView(移动端)或激活桌面窗口(桌面端),然后触发login事件。
第 3 步:处理回调与登录事件
Auth0 将用户重定向到redirect_url并携带code与state。Flet 的_authorize_callback()(page.py)负责:
- 校验
state与发起登录时生成的值一致; - 非 Web 端根据平台关闭授权 WebView 或把桌面窗口置前;
- 构造
LoginEvent,若回调中带error/error_description则原样透出; - 否则取出
code,调用AuthorizationService.request_token(code)换取令牌; - 触发
on_login事件处理器。
登出则调用page.logout(),它会清空当前认证上下文并触发logout事件。
底层流程:令牌交换、用户资料与自动刷新
Auth0OAuthProvider本身只描述配置,真正的流程编排由AuthorizationService(authorization_service.py)完成。page.login()内部会构造一个AuthorizationService(provider, fetch_user, fetch_groups, scope),其工作流程如下:
构造授权 URL:
get_authorization_data()使用secrets.token_urlsafe(16)生成 CSRFstate,再借助oauthlib.oauth2.WebApplicationClient将client_id、redirect_url、合并后的scope、state以及provider.authorization_params(含可选的audience)拼接到https://{domain}/authorize。返回(authorization_url, state)。令牌交换:回调拿到
code后,request_token(code)以表单格式 POST 到https://{domain}/oauth/token,请求体包含code、redirect_uri、client_secret等字段,请求头带有User-Agent: Flet/{flet_version}。成功后将 oauthlib 返回的映射转换为OAuthToken对象。用户资料加载:
__fetch_user_and_groups()在fetch_user=True时优先调用provider._fetch_user(access_token)钩子;由于 Auth0 预设没有重写该方法(基类返回None),会回退到通用路径:携带Authorization: Bearer <token>请求https://{domain}/userinfo,用user_id_fn(即lambda u: u["sub"])从 JSON 中提取sub作为用户 ID,构造User实例。注意:若配置了user_endpoint而未配置user_id_fn,会抛出ValueError。令牌刷新:
get_token()与dehydrate_token()都会触发__refresh_token()——当令牌已过期且存在refresh_token时,向令牌端点发起刷新请求;若刷新响应未携带新的refresh_token,则沿用旧值。这解释了为何预设请求offline_access作用域:它是获取刷新令牌的前提。
用户与令牌模型
User(user.py)是dict的子类,保存提供商返回的全部字段(如name、email、picture),并带有规范化属性id(来自sub)与groups列表。OAuthToken(oauth_token.py)保存access_token、scope、token_type、expires_in、expires_at、refresh_token,并提供to_json()/from_json()用于序列化持久化。将saved_token传给page.login()后,dehydrate_token()会反序列化、必要时刷新并在可用时加载用户与分组——这是实现"记住登录状态"的推荐路径。
常见注意事项
domain不要带协议:源码直接拼接f"https://{domain}/authorize",传入https://example.us.auth0.com会得到错误的端点 URL。redirect_url必须精确匹配:Auth0 回调地址校验是严格匹配的,末尾斜杠、端口差异都会导致回调失败。audience按需传入:仅当你的访问令牌要调用 Auth0 保护的 API 时才需要设置;不设置则无法获取面向该 API 的权限声明。offline_access是固定作用域:它保证了刷新令牌可用,勿在自定义scope中与之冲突。- 回调地址建议使用本地约定:
http://localhost:8550/oauth_callback与 cookbook/authentication.md 中的示例保持一致,便于联调。
总结
Auth0OAuthProvider是 Flet 认证体系中"开箱即用"的 Auth0 预设:只需 5 个构造参数即可获得完整的授权端点、作用域、用户资料与刷新令牌配置,再配合page.login()、page.on_login与OAuthToken持久化,即可在桌面、Web 与移动端 Flet 应用中快速落地 Auth0 登录。其源码(auth0_oauth_provider.py)与流程编排(authorization_service.py)均可在本仓库中直接查阅,便于进一步定制或扩展。
【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考