better-auth-tauri-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Better Auth Tauri Plugin - Setup Guide

Better Auth Tauri 插件 - 安装指南

Package:
@daveyplate/better-auth-tauri
(v0.1.6+) Purpose: Enables cookie-based authentication in Tauri v2 desktop apps using deep links for OAuth callback flows.

@daveyplate/better-auth-tauri
(v0.1.6+) 用途:通过 OAuth 回调流程的深度链接,在 Tauri v2 桌面应用中启用基于 Cookie 的认证。

Architecture Overview

架构概述

The plugin works in two halves: a server plugin (Better Auth middleware) and a client setup (Tauri deep link listener). Social OAuth opens in the user's default browser, completes there, then deep-links back into the Tauri app to finalize the session.
该插件分为两部分工作:服务端插件(Better Auth 中间件)和客户端配置(Tauri 深度链接监听器)。社交 OAuth 在用户默认浏览器中打开并完成认证,随后通过深度链接跳转回 Tauri 应用以完成会话建立。

Complete Social Auth Flow

完整社交认证流程

1. 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 complete

1. 用户在 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 回调触发——认证完成

Prerequisites

前置条件

Required Tauri Plugins (peer dependencies)

必需的 Tauri 插件(对等依赖)

bash
bun add @tauri-apps/api @tauri-apps/plugin-deep-link @tauri-apps/plugin-http @tauri-apps/plugin-os @tauri-apps/plugin-opener better-auth
PluginMin VersionPurpose
@tauri-apps/api
>=2.5.0Core Tauri API,
isTauri()
check
@tauri-apps/plugin-deep-link
>=2.2.1URL scheme handling (
onOpenUrl
)
@tauri-apps/plugin-http
>=2.4.3HTTP with cookie support (macOS fix)
@tauri-apps/plugin-os
>=2.2.1Platform detection
@tauri-apps/plugin-opener
>=2.2.6Open OAuth URLs in default browser
better-auth
>=1.2.7Authentication framework
bash
bun add @tauri-apps/api @tauri-apps/plugin-deep-link @tauri-apps/plugin-http @tauri-apps/plugin-os @tauri-apps/plugin-opener better-auth
插件最低版本用途
@tauri-apps/api
>=2.5.0Tauri 核心 API,用于
isTauri()
检测
@tauri-apps/plugin-deep-link
>=2.2.1URL scheme 处理(
onOpenUrl
@tauri-apps/plugin-http
>=2.4.3支持 Cookie 的 HTTP 请求(修复 macOS 兼容问题)
@tauri-apps/plugin-os
>=2.2.1平台检测
@tauri-apps/plugin-opener
>=2.2.6在默认浏览器中打开 OAuth 地址
better-auth
>=1.2.7认证框架

Tauri Deep Link Config

Tauri 深度链接配置

In
tauri.conf.json
:
json
{
  "plugins": {
    "deep-link": {
      "desktop": {
        "schemes": ["my-app"]
      }
    }
  }
}

tauri.conf.json
中:
json
{
  "plugins": {
    "deep-link": {
      "desktop": {
        "schemes": ["my-app"]
      }
    }
  }
}

Server Setup

服务端配置

Plugin Registration (auth.ts)

插件注册(auth.ts)

typescript
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
    }),
  ],
})
typescript
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,        // 启用服务端调试日志
    }),
  ],
})

Plugin Options

插件选项

OptionTypeDefaultDescription
scheme
string
requiredDeep link scheme (without
://
)
callbackURL
string
"/"
Post-auth redirect path
successText
string
Generic messageText shown on browser success page
successURL
string
undefined
Custom success page URL (receives
?redirectTo=
)
debugLogs
boolean
false
Log middleware activity to console
选项类型默认值描述
scheme
string
必填深度链接 scheme(不含
://
callbackURL
string
"/"
认证后的重定向路径
successText
string
通用提示语浏览器成功页面显示的文本
successURL
string
undefined
自定义成功页面地址(会接收
?redirectTo=
参数)
debugLogs
boolean
false
在控制台输出中间件活动日志

What the Server Plugin Does

服务端插件功能

The plugin registers:
  1. Before-hook middleware on all routes (except
    /reset-password
    and
    /callback/success
    ):
    • appendCallbackURL()
      : On
      /sign-in/social
      requests with a
      Platform
      header (non-mobile), modifies each social provider's
      redirectURI
      to include
      ?callbackURL=scheme://
    • checkCallbackURL()
      : On any request where
      callbackURL
      query param starts with
      scheme://
      , strips the scheme and redirects to the success page with the deep link URL encoded in
      ?redirectTo=
  2. Endpoint
    /callback/success
    : Returns HTML success page with embedded
    <script>window.location.href = '{deepLinkURL}'</script>
    to trigger the OS deep link

该插件会注册:
  1. 所有路由的前置钩子中间件(除了
    /reset-password
    /callback/success
    ):
    • appendCallbackURL()
      :当
      /sign-in/social
      请求带有
      Platform
      请求头(非移动端)时,修改每个社交提供商的
      redirectURI
      ,追加
      ?callbackURL=scheme://
    • checkCallbackURL()
      :当任何请求的
      callbackURL
      查询参数以
      scheme://
      开头时,移除 scheme 并将请求重定向到成功页面,同时将深度链接地址编码到
      ?redirectTo=
      参数中
  2. 端点
    /callback/success
    :返回包含
    <script>window.location.href = '{deepLinkURL}'</script>
    的 HTML 成功页面,触发系统深度链接

Client Setup

客户端配置

Auth Client with macOS Cookie Fix

适配 macOS Cookie 问题的认证客户端

Critical: macOS production builds require
@tauri-apps/plugin-http
for cookies to work.
typescript
// 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)
  }
})
关键注意:macOS 生产构建需要
@tauri-apps/plugin-http
才能正常使用 Cookie。
typescript
// 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)
  }
})

Standard JS/TS Setup

标准 JS/TS 配置

typescript
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)
typescript
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()(例如组件卸载时)

React Setup

React 配置

tsx
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 />
}
tsx
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 />
}

Svelte Setup

Svelte 配置

svelte
<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>

svelte
<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>

Social Sign-In

社交登录

Social auth opens in the user's default browser (reuses logged-in sessions). Use the provided helper:
tsx
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>
社交认证会在用户默认浏览器中打开(复用已登录会话)。使用提供的工具函数:
tsx
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>

What signInSocial Does

signInSocial 功能说明

  1. Checks if Opener plugin is available (
    isTauri()
    + correct protocol)
  2. Sends sign-in request with
    Platform
    header (triggers server-side callback URL appending)
  3. Sets
    disableRedirect: true
    to prevent in-app redirect
  4. Opens returned OAuth URL in default browser via
    openUrl()
  5. Supports
    fetchOptions.throw: true
    for exception-based error handling
  1. 检查 Opener 插件是否可用(
    isTauri()
    + 正确协议)
  2. 发送带有
    Platform
    请求头的登录请求(触发服务端回调地址追加逻辑)
  3. 设置
    disableRedirect: true
    以避免应用内重定向
  4. 通过
    openUrl()
    在默认浏览器中打开返回的 OAuth 地址
  5. 支持
    fetchOptions.throw: true
    实现基于异常的错误处理

Non-Social Auth (Magic Link, Email OTP)

非社交认证(魔法链接、邮箱OTP)

Works via the
callbackURL
plugin option. The email link contains the deep link scheme directly. No special client-side helper needed - just configure
scheme
in the server plugin and the link in the email will deep-link back to the app.

通过
callbackURL
插件选项实现。邮箱链接直接包含深度链接 scheme。无需特殊客户端工具函数——只需在服务端插件中配置
scheme
,邮箱中的链接即可直接深度链接回应用。

Package Exports

包导出

@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(服务端插件工厂)

Quick Checklist

快速检查清单

  • Install all 5 Tauri plugin peer dependencies
  • Register deep link scheme in
    tauri.conf.json
  • Add
    tauri()
    plugin to server
    betterAuth()
    config with matching scheme
  • Configure
    customFetchImpl
    in auth client for macOS cookies
  • Call
    setupBetterAuthTauri()
    (or
    useBetterAuthTauri
    ) in app entry point
  • Use
    signInSocial()
    helper for social providers (not
    authClient.signIn.social()
    directly)
  • Ensure server has a root route handler (
    GET /
    ) to avoid 404 on post-auth redirect
  • Scheme must be identical across:
    tauri.conf.json
    , server plugin, and client setup

  • 安装所有5个Tauri插件对等依赖
  • tauri.conf.json
    中注册深度链接 scheme
  • 在服务端
    betterAuth()
    配置中添加
    tauri()
    插件,并使用匹配的 scheme
  • 在认证客户端中配置
    customFetchImpl
    以适配 macOS Cookie
  • 在应用入口调用
    setupBetterAuthTauri()
    (或
    useBetterAuthTauri
  • 使用
    signInSocial()
    工具函数处理社交提供商(不要直接使用
    authClient.signIn.social()
  • 确保服务端有根路由处理器(
    GET /
    ),避免认证后重定向出现404
  • scheme 必须在以下位置保持一致:
    tauri.conf.json
    、服务端插件、客户端配置

Related Skills

相关技能

  • sawy-better-auth-ui-tauri-repro: Reproduction and fix for the
    @daveyplate/better-auth-ui
    module-load-time crash in non-HTTP environments (
    BetterAuthError: Invalid base URL: tauri://localhost
    ). Covers pnpm patching, upstream fix proposals, and diagnostic tooling.
  • better-auth-tauri-pitfalls: Debugging guide covering 10 known pitfalls — 404 after OAuth, macOS deep links, cookie persistence, scheme mismatches, and more.
<!-- cross-ref:start -->
  • sawy-better-auth-ui-tauri-repro:针对
    @daveyplate/better-auth-ui
    在非HTTP环境下加载时崩溃问题的复现与修复(
    BetterAuthError: Invalid base URL: tauri://localhost
    )。涵盖pnpm补丁、上游修复方案和诊断工具。
  • better-auth-tauri-pitfalls:调试指南,涵盖10个已知问题——OAuth后404、macOS深度链接、Cookie持久化、scheme不匹配等。
<!-- cross-ref:start -->

See also (related skills — Better Auth family)

另请参阅(相关技能 — Better Auth 系列)

If your issue relates to:
  • Better Auth integration overview — check
    better-auth
    if appropriate.
  • best-practices guide — check
    better-auth-best-practices
    if appropriate.
  • create the auth layer (initial scaffolding) — check
    better-auth-create-auth
    if appropriate.
  • email/password, password reset, verification policies — check
    better-auth-email-password
    if appropriate.
  • explain a specific error code + provide fix — check
    better-auth-explain-error
    if appropriate.
  • organization/team plugin — check
    better-auth-organization
    if appropriate.
  • OAuth/email/magic-link/social provider config — check
    better-auth-providers
    if appropriate.
  • rate limit, CSRF, trusted origins, secrets, OAuth security — check
    better-auth-security
    if appropriate.
  • twoFactor plugin enforcement — check
    better-auth-two-factor
    if appropriate.
  • Tauri-specific gotchas (cookies, deep links, macOS, 404 callbacks) — check
    better-auth-tauri-pitfalls
    if appropriate.
  • reproduction guide for the better-auth-ui crash on Tauri v2 — check
    sawy-better-auth-ui-tauri-repro
    if appropriate.
<!-- cross-ref:end -->
如果您的问题涉及:
  • Better Auth 集成概述 — 如有需要,请查看
    better-auth
  • 最佳实践指南 — 如有需要,请查看
    better-auth-best-practices
  • 创建认证层(初始脚手架) — 如有需要,请查看
    better-auth-create-auth
  • 邮箱/密码、密码重置、验证策略 — 如有需要,请查看
    better-auth-email-password
  • 解释特定错误码 + 提供修复方案 — 如有需要,请查看
    better-auth-explain-error
  • 组织/团队插件 — 如有需要,请查看
    better-auth-organization
  • OAuth/邮箱/魔法链接/社交提供商配置 — 如有需要,请查看
    better-auth-providers
  • 速率限制、CSRF、可信源、密钥、OAuth安全 — 如有需要,请查看
    better-auth-security
  • 双因素插件强制验证 — 如有需要,请查看
    better-auth-two-factor
  • Tauri特定问题(Cookie、深度链接、macOS、404回调) — 如有需要,请查看
    better-auth-tauri-pitfalls
  • Better-auth-ui在Tauri v2中崩溃问题的复现指南 — 如有需要,请查看
    sawy-better-auth-ui-tauri-repro
<!-- cross-ref:end -->