身份认证
由功能开关控制的邮箱认证、OTP 流程与系统钥匙串会话存储。
认证由 VITE_AUTH_ENABLED 控制,默认启用。模板提供 Supabase 邮箱/密码登录、注册
验证、密码找回、账户页面、资料编辑与私有头像上传。
开关与启动行为
| 条件 | 结果 |
|---|---|
VITE_AUTH_ENABLED=true(默认) | 显示登录和账户界面,并要求有效 Supabase URL 与 publishable key。 |
| 认证开启但 URL 缺失/无效或 key 缺失 | main.tsx 在导入 App 前显示 SupabaseConfigErrorScreen。 |
VITE_AUTH_ENABLED=false | 认证界面与 store 活动均被移除;应用成为纯本地桌面应用。Supabase client 变为可安全导入的 proxy,只有意外使用时才抛出错误。 |
因此本地构建无需伪造后端。计费还有独立的 VITE_BILLING_ENABLED 开关。
邮箱流程
src/routes/auth/ 的页面共用居中的 AuthCard。表单由 React Hook Form 与
src/lib/auth/auth-schemas.ts 的 Zod schema 驱动:
| 流程 | 路由 | 实现 |
|---|---|---|
| 登录 | /login | signInWithPassword |
| 创建账户 | /register | signUp,将 full_name 写入 metadata |
| 确认账户 | 注册页验证步骤 | 使用 type: 'signup' 的六码 verifyOtp;重发冷却 30 秒 |
| 开始找回 | /forgot-password | resetPasswordForEmail |
| 设置新密码 | /reset-password | recovery verifyOtp → updateUser → signOut |
密码至少八位,且必须包含字母和数字。在 Supabase 的注册、找回邮件模板中展示
{{ .Token }}。这些是输入验证码的流程,不是 magic-link 重定向;客户端刻意设置
detectSessionInUrl: false。
当前模板没有接入 OAuth。添加 Google、GitHub 或 Apple 时,除了在 Supabase 开启 provider,还要注册安全的深链回调:在 Supabase 添加改品牌后的 scheme,并把回调加入 应用意图 allow-list。详见 Supabase 配置 与 深层链接。
会话状态与钥匙串
src/stores/auth-store.ts 管理 renderer 的 unknown、authenticated、
unauthenticated 状态以及 user、session、profile。启动时读取会话,之后监听
Supabase 认证事件;登录、初始会话、token 刷新和用户更新会刷新资料,登出会清空资料。
会话不会保存在普通浏览器存储中:
supabase-js storage adapter
→ src/lib/tauri/secure.ts
→ 自动生成的 secure commands
→ src-tauri/src/commands/secure.rs
→ OS keychain(Rust keyring crate)Supabase 可变的存储 key 被映射到固定钥匙串槽位 supabase-session,启动时还会删除
遗留 localStorage 会话。原生 SecureKey enum 是白名单:access-token、
refresh-token、supabase-session、license-key、showcase-secret,因此 webview
无法试探任意钥匙串名称。
| 失败 | 读取行为 | 写入/删除行为 |
|---|---|---|
ENCRYPTION_UNAVAILABLE | 返回 null,Supabase 视为未登录。 | 操作失败,不会回退为明文保存。 |
STORAGE_FAILURE | 返回 null;应用可继续运行,但不会恢复旧会话。 | 返回原生错误。 |
未签名的 macOS 开发构建出现钥匙串访问提示是正常的。允许访问即可测试持久登录,不要
为绕过提示而改回 localStorage。
账户、资料与头像
src/routes/AccountPage.tsx 渲染账户设置区,src/services/profile.ts 读写
profiles 行,src/services/avatar.ts 完成头像流程。
| 项目 | 当前行为 |
|---|---|
| 资料字段 | full_name、bio、phone、location、avatar_url |
| 图片验证 | PNG、JPEG 或 WebP;非空且不超过 5 MB |
| 上传路径 | avatars/<user-id>/avatar.<ext> |
| 桶可见性 | 私有;RLS 将所有操作限制在所有者目录 |
| 展示地址 | 七天有效的签名 URL,并以 profiles.updated_at 作为缓存键 |
资料与头像是示例功能,但其中的模式可直接用于生产:前端验证、所有者范围的 Storage RLS、保存路径而非公开 URL,以及短期签名读取。启用前先执行 Supabase 配置 中的 SQL。
验证认证
- 认证开启时移除 URL 或 publishable key,确认显示配置错误界面而非损坏的 shell。
- 注册、输入六码验证码,并确认已有
profiles行。 - 登出、重新登录、重启应用,确认钥匙串恢复会话。
- 完成找回/重设密码,确认流程结束于登录页。
- 在账户页上传并删除头像。
