Loading...
Loading...
Compare original and translation side by side
@daveyplate/better-auth-tauri@daveyplate/better-auth-tauri1. User clicks "Sign in with Google" in Tauri app
2. signInSocial() sends request to /api/auth/sign-in/social with Platform header
3. Server middleware appends scheme callback to OAuth redirectURI:
→ /api/auth/callback/google?callbackURL=my-app://
4. Server returns Google OAuth URL; client opens it in default browser
5. User authenticates in browser; Google redirects to callback URL
6. Server middleware intercepts callbackURL with scheme prefix
7. Server redirects to /api/auth/callback/success?redirectTo=my-app://api/auth/callback/google?...
8. Success page HTML triggers: window.location.href = 'my-app://...'
9. OS deep link activates Tauri app
10. Client handleAuthDeepLink() calls authClient.$fetch() to process callback
11. Server validates OAuth code, creates session, sets cookie
12. onSuccess callback fires - auth complete1. 用户在 Tauri 应用中点击“使用 Google 登录”
2. signInSocial() 向 /api/auth/sign-in/social 发送请求,附带 Platform 请求头
3. 服务端中间件在 OAuth 的 redirectURI 后追加 scheme 回调地址:
→ /api/auth/callback/google?callbackURL=my-app://
4. 服务端返回 Google OAuth 地址;客户端在默认浏览器中打开该地址
5. 用户在浏览器中完成认证;Google 重定向到回调地址
6. 服务端中间件拦截带有 scheme 前缀的 callbackURL 请求
7. 服务端重定向到 /api/auth/callback/success?redirectTo=my-app://api/auth/callback/google?...
8. 成功页面的 HTML 触发:window.location.href = 'my-app://...'
9. 系统深度链接激活 Tauri 应用
10. 客户端调用 handleAuthDeepLink(),通过 authClient.$fetch() 处理回调
11. 服务端验证 OAuth 授权码,创建会话并设置 Cookie
12. onSuccess 回调触发——认证完成bun add @tauri-apps/api @tauri-apps/plugin-deep-link @tauri-apps/plugin-http @tauri-apps/plugin-os @tauri-apps/plugin-opener better-auth| Plugin | Min Version | Purpose |
|---|---|---|
| >=2.5.0 | Core Tauri API, |
| >=2.2.1 | URL scheme handling ( |
| >=2.4.3 | HTTP with cookie support (macOS fix) |
| >=2.2.1 | Platform detection |
| >=2.2.6 | Open OAuth URLs in default browser |
| >=1.2.7 | Authentication framework |
bun add @tauri-apps/api @tauri-apps/plugin-deep-link @tauri-apps/plugin-http @tauri-apps/plugin-os @tauri-apps/plugin-opener better-auth| 插件 | 最低版本 | 用途 |
|---|---|---|
| >=2.5.0 | Tauri 核心 API,用于 |
| >=2.2.1 | URL scheme 处理( |
| >=2.4.3 | 支持 Cookie 的 HTTP 请求(修复 macOS 兼容问题) |
| >=2.2.1 | 平台检测 |
| >=2.2.6 | 在默认浏览器中打开 OAuth 地址 |
| >=1.2.7 | 认证框架 |
tauri.conf.json{
"plugins": {
"deep-link": {
"desktop": {
"schemes": ["my-app"]
}
}
}
}tauri.conf.json{
"plugins": {
"deep-link": {
"desktop": {
"schemes": ["my-app"]
}
}
}
}import { betterAuth } from "better-auth"
import { tauri } from "@daveyplate/better-auth-tauri/plugin"
export const auth = betterAuth({
// ... your existing config
plugins: [
tauri({
scheme: "my-app", // Must match tauri.conf.json and client
callbackURL: "/", // Where to redirect after auth (default: "/")
successText: "Authentication successful! You can close this window.",
successURL: undefined, // Custom success page URL (gets ?redirectTo param)
debugLogs: false, // Enable server-side debug logging
}),
],
})import { betterAuth } from "better-auth"
import { tauri } from "@daveyplate/better-auth-tauri/plugin"
export const auth = betterAuth({
// ... 您现有的配置
plugins: [
tauri({
scheme: "my-app", // 必须与 tauri.conf.json 和客户端配置一致
callbackURL: "/", // 认证完成后的重定向地址(默认:"/")
successText: "认证成功!您可以关闭此窗口。",
successURL: undefined, // 自定义成功页面地址(会接收 ?redirectTo 参数)
debugLogs: false, // 启用服务端调试日志
}),
],
})| Option | Type | Default | Description |
|---|---|---|---|
| | required | Deep link scheme (without |
| | | Post-auth redirect path |
| | Generic message | Text shown on browser success page |
| | | Custom success page URL (receives |
| | | Log middleware activity to console |
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| | 必填 | 深度链接 scheme(不含 |
| | | 认证后的重定向路径 |
| | 通用提示语 | 浏览器成功页面显示的文本 |
| | | 自定义成功页面地址(会接收 |
| | | 在控制台输出中间件活动日志 |
/reset-password/callback/successappendCallbackURL()/sign-in/socialPlatformredirectURI?callbackURL=scheme://checkCallbackURL()callbackURLscheme://?redirectTo=/callback/success<script>window.location.href = '{deepLinkURL}'</script>/reset-password/callback/successappendCallbackURL()/sign-in/socialPlatformredirectURI?callbackURL=scheme://checkCallbackURL()callbackURLscheme://?redirectTo=/callback/success<script>window.location.href = '{deepLinkURL}'</script>@tauri-apps/plugin-http// lib/auth-client.ts
import { isTauri } from "@tauri-apps/api/core"
import { fetch as tauriFetch } from "@tauri-apps/plugin-http"
import { platform } from "@tauri-apps/plugin-os"
import { createAuthClient } from "better-auth/react" // or "better-auth/client"
export const authClient = createAuthClient({
fetchOptions: {
customFetchImpl: (...params) =>
isTauri() && platform() === "macos" && window.location.protocol === "tauri:"
? tauriFetch(...params)
: fetch(...params)
}
})@tauri-apps/plugin-http// lib/auth-client.ts
import { isTauri } from "@tauri-apps/api/core"
import { fetch as tauriFetch } from "@tauri-apps/plugin-http"
import { platform } from "@tauri-apps/plugin-os"
import { createAuthClient } from "better-auth/react" // 或 "better-auth/client"
export const authClient = createAuthClient({
fetchOptions: {
customFetchImpl: (...params) =>
isTauri() && platform() === "macos" && window.location.protocol === "tauri:"
? tauriFetch(...params)
: fetch(...params)
}
})import { setupBetterAuthTauri } from "@daveyplate/better-auth-tauri"
import { authClient } from "./lib/auth-client"
const cleanup = setupBetterAuthTauri({
authClient,
scheme: "my-app", // Must match server config
debugLogs: false,
mainWindowLabel: "main", // Tauri window label (default: "main")
onRequest: (href) => {
console.log("Processing auth callback:", href)
},
onSuccess: (callbackURL) => {
window.location.href = callbackURL || "/"
},
onError: (error) => {
// error: { status: number, statusText: string, code?: string, message?: string }
console.error("Auth failed:", error.status, error.statusText)
},
})
// Call cleanup() when done (e.g., component unmount)import { setupBetterAuthTauri } from "@daveyplate/better-auth-tauri"
import { authClient } from "./lib/auth-client"
const cleanup = setupBetterAuthTauri({
authClient,
scheme: "my-app", // 必须与服务端配置一致
debugLogs: false,
mainWindowLabel: "main", // Tauri 窗口标签(默认:"main")
onRequest: (href) => {
console.log("处理认证回调:", href)
},
onSuccess: (callbackURL) => {
window.location.href = callbackURL || "/"
},
onError: (error) => {
// error: { status: number, statusText: string, code?: string, message?: string }
console.error("认证失败:", error.status, error.statusText)
},
})
// 完成后调用 cleanup()(例如组件卸载时)import { useBetterAuthTauri } from "@daveyplate/better-auth-tauri/react"
import { authClient } from "./lib/auth-client"
function App() {
useBetterAuthTauri({
authClient,
scheme: "my-app",
onSuccess: (callbackURL) => {
navigate(callbackURL || "/")
},
onError: (error) => {
toast.error(`Auth failed: ${error.statusText}`)
},
})
return <YourApp />
}import { useBetterAuthTauri } from "@daveyplate/better-auth-tauri/react"
import { authClient } from "./lib/auth-client"
function App() {
useBetterAuthTauri({
authClient,
scheme: "my-app",
onSuccess: (callbackURL) => {
navigate(callbackURL || "/")
},
onError: (error) => {
toast.error(`认证失败: ${error.statusText}`)
},
})
return <YourApp />
}<script>
import { onMount, onDestroy } from "svelte"
import { setupBetterAuthTauri } from "@daveyplate/better-auth-tauri"
import { authClient } from "./lib/auth-client"
import { goto } from "$app/navigation"
let cleanup
onMount(() => {
cleanup = setupBetterAuthTauri({
authClient,
scheme: "my-app",
onSuccess: (callbackURL) => goto(callbackURL || "/"),
onError: (error) => console.error("Auth error:", error),
})
})
onDestroy(() => cleanup?.())
</script><script>
import { onMount, onDestroy } from "svelte"
import { setupBetterAuthTauri } from "@daveyplate/better-auth-tauri"
import { authClient } from "./lib/auth-client"
import { goto } from "$app/navigation"
let cleanup
onMount(() => {
cleanup = setupBetterAuthTauri({
authClient,
scheme: "my-app",
onSuccess: (callbackURL) => goto(callbackURL || "/"),
onError: (error) => console.error("认证错误:", error),
})
})
onDestroy(() => cleanup?.())
</script>import { signInSocial } from "@daveyplate/better-auth-tauri"
import { authClient } from "./lib/auth-client"
<button onClick={async () => {
const { data, error } = await signInSocial({
authClient,
provider: "google", // Any configured social provider
})
if (error) console.error("Social sign-in error:", error)
}}>
Sign in with Google
</button>import { signInSocial } from "@daveyplate/better-auth-tauri"
import { authClient } from "./lib/auth-client"
<button onClick={async () => {
const { data, error } = await signInSocial({
authClient,
provider: "google", // 任何已配置的社交提供商
})
if (error) console.error("社交登录错误:", error)
}}>
使用 Google 登录
</button>isTauri()PlatformdisableRedirect: trueopenUrl()fetchOptions.throw: trueisTauri()PlatformdisableRedirect: trueopenUrl()fetchOptions.throw: truecallbackURLschemecallbackURLscheme@daveyplate/better-auth-tauri → setupBetterAuthTauri, signInSocial, handleAuthDeepLink
@daveyplate/better-auth-tauri/react → useBetterAuthTauri (React hook)
@daveyplate/better-auth-tauri/plugin → tauri (server plugin factory)@daveyplate/better-auth-tauri → setupBetterAuthTauri, signInSocial, handleAuthDeepLink
@daveyplate/better-auth-tauri/react → useBetterAuthTauri(React 钩子)
@daveyplate/better-auth-tauri/plugin → tauri(服务端插件工厂)tauri.conf.jsontauri()betterAuth()customFetchImplsetupBetterAuthTauri()useBetterAuthTaurisignInSocial()authClient.signIn.social()GET /tauri.conf.jsontauri.conf.jsonbetterAuth()tauri()customFetchImplsetupBetterAuthTauri()useBetterAuthTaurisignInSocial()authClient.signIn.social()GET /tauri.conf.json@daveyplate/better-auth-uiBetterAuthError: Invalid base URL: tauri://localhost@daveyplate/better-auth-uiBetterAuthError: Invalid base URL: tauri://localhostbetter-authbetter-auth-best-practicesbetter-auth-create-authbetter-auth-email-passwordbetter-auth-explain-errorbetter-auth-organizationbetter-auth-providersbetter-auth-securitybetter-auth-two-factorbetter-auth-tauri-pitfallssawy-better-auth-ui-tauri-reprobetter-authbetter-auth-best-practicesbetter-auth-create-authbetter-auth-email-passwordbetter-auth-explain-errorbetter-auth-organizationbetter-auth-providersbetter-auth-securitybetter-auth-two-factorbetter-auth-tauri-pitfallssawy-better-auth-ui-tauri-repro