基本用法

入门 Better Auth

Better Auth 提供内置的认证支持:

  • Email and password
  • Social provider (Google, GitHub, Apple, and more)

同时也可以通过插件轻松扩展,例如:用户名魔法链接通行密钥邮箱验证码 等。

邮箱 & 密码

启用邮箱和密码认证:

auth.ts
import { betterAuth } from "better-auth"

export const auth = betterAuth({
    emailAndPassword: {    
        enabled: true
    } 
})

注册

要注册用户,需要调用客户端方法 signUp.email 并传入用户信息。

sign-up.ts
import { authClient } from "@/lib/auth-client"; // 导入认证客户端

const { data, error } = await authClient.signUp.email({
        email, // 用户邮箱地址
        password, // 用户密码 -> 默认最少8个字符
        name, // 用户显示名称
        image, // 用户头像 URL(可选)
        callbackURL: "/dashboard" // 用户验证邮箱后跳转的 URL(可选)
    }, {
        onRequest: (ctx) => {
            // 显示加载中
        },
        onSuccess: (ctx) => {
            // 跳转到仪表盘或登录页
        },
        onError: (ctx) => {
            // 显示错误信息
            alert(ctx.error.message);
        },
});

默认情况下,用户注册成功后会自动登录。如需禁用此行为,可以将 autoSignIn 设置为 false

auth.ts
import { betterAuth } from "better-auth"

export const auth = betterAuth({
    emailAndPassword: {
    	enabled: true,
    	autoSignIn: false // 默认为 true
  },
})

Sign In

要登录用户,可以使用客户端提供的 signIn.email 函数。

sign-in
const { data, error } = await authClient.signIn.email({
        /**
         * 用户邮箱
         */
        email,
        /**
         * 用户密码
         */
        password,
        /**
         * 用户验证邮箱后跳转的 URL(可选)
         */
        callbackURL: "/dashboard",
        /**
         * 浏览器关闭后是否记住用户会话。
         * @default true
         */
        rememberMe: false
}, {
    // 回调函数
})

Always invoke client methods from the client side. Don't call them from the server.

服务器端认证

要在服务器端认证用户,可以使用 auth.api 方法。

server.ts
import { auth } from "./auth"; // 你的 Better Auth 服务器实例路径

const response = await auth.api.signInEmail({
    body: {
        email,
        password
    },
    asResponse: true // 返回响应对象而非数据
});

If the server cannot return a response object, you'll need to manually parse and set cookies. But for frameworks like Next.js we provide a plugin to handle this automatically

社交登录

Better Auth 支持多种社交提供商,包括 Google、GitHub、Apple、Discord 等。使用社交提供商时,需在 auth 对象的 socialProviders 选项中配置相应的提供商。

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
    socialProviders: { 
        github: { 
            clientId: process.env.GITHUB_CLIENT_ID!, 
            clientSecret: process.env.GITHUB_CLIENT_SECRET!, 
        } 
    }, 
})

使用社交提供商登录

要使用社交提供商登录,调用 signIn.social,并传入如下属性对象:

sign-in.ts
import { authClient } from "@/lib/auth-client"; //导入认证客户端

await authClient.signIn.social({
    /**
     * 社交提供商 ID
     * @example "github", "google", "apple"
     */
    provider: "github",
    /**
     * 用户通过提供商认证后重定向的 URL
     * @default "/"
     */
    callbackURL: "/dashboard", 
    /**
     * 登录过程中发生错误时重定向的 URL
     */
    errorCallbackURL: "/error",
    /**
     * 用户新注册时重定向的 URL
     */
    newUserCallbackURL: "/welcome",
    /**
     * 禁用自动跳转至提供商。
     * @default false
     */
    disableRedirect: true,
});

You can also authenticate using idToken or accessToken from the social provider instead of redirecting the user to the provider's site. See social providers documentation for more details.

登出

要登出用户,可以使用客户端提供的 signOut 函数。

user-card.tsx
await authClient.signOut();

you can pass fetchOptions to redirect onSuccess

user-card.tsx
await authClient.signOut({
  fetchOptions: {
    onSuccess: () => {
      router.push("/login"); // 跳转到登录页
    },
  },
});

会话

用户登录后,你可能需要访问用户会话。Better Auth 支持在服务端和客户端轻松访问会话数据。

客户端

使用会话

Better Auth 提供了 useSession 钩子,用于客户端轻松访问会话数据。该钩子基于 nanostore 实现,支持所有主流框架和原生客户端,可确保会话状态变化(如登出)立即更新 UI。

user.tsx
import { authClient } from "@/lib/auth-client" // import the auth client

export function User(){

    const { 
        data: session, 
        isPending, //loading state
        error, //error object
        refetch //refetch the session
    } = authClient.useSession() 

    return (
        //...
    )
}
index.vue
<script setup lang="ts">
import { authClient } from "~/lib/auth-client"

const session = authClient.useSession() 
</script>

<template>
    <div>
        <div>
            <pre>{{ session.data }}</pre>
            <button v-if="session.data" @click="authClient.signOut()">
                Sign out
            </button>
        </div>
    </div>
</template>
user.svelte
<script lang="ts">
import { authClient } from "$lib/auth-client"; 

const session = authClient.useSession(); 
</script>
<p>
    {$session.data?.user.email}
</p>
auth-client.ts
import { authClient } from "~/lib/auth-client"; //import the auth client

authClient.useSession.subscribe((value)=>{
    //do something with the session //
}) 
user.tsx
import { authClient } from "~/lib/auth-client"; 

export default function Home() {
    const session = authClient.useSession() 
    return (
        <pre>{JSON.stringify(session(), null, 2)}</pre>
    );
}

获取会话

如果不想使用钩子,也可以调用客户端的 getSession 方法。

user.tsx
import { authClient } from "@/lib/auth-client" // 导入认证客户端

const { data: session, error } = await authClient.getSession()

它也可与客户端数据获取库结合使用,比如 TanStack Query

服务器端

服务器端提供了一个 session 对象,用于访问会话数据。需要传入请求头对象给 getSession 方法。

示例:使用流行框架

server.ts
import { auth } from "./auth"; // 你的 Better Auth 服务器实例路径
import { headers } from "next/headers";

const session = await auth.api.getSession({
    headers: await headers() // 需传入请求头对象
})
route.ts
import { auth } from "lib/auth"; // 你的 Better Auth 服务器实例路径

export async function loader({ request }: LoaderFunctionArgs) {
    const session = await auth.api.getSession({
        headers: request.headers
    })

    return json({ session })
}
index.astro
---
import { auth } from "./auth";

const session = await auth.api.getSession({
    headers: Astro.request.headers,
});
---
<!-- 你的 Astro 模板 -->
+page.ts
import { auth } from "./auth";

export async function load({ request }) {
    const session = await auth.api.getSession({
        headers: request.headers
    })
    return {
        props: {
            session
        }
    }
}
index.ts
import { auth } from "./auth";

const app = new Hono();

app.get("/path", async (c) => {
    const session = await auth.api.getSession({
        headers: c.req.raw.headers
    })
});
server/session.ts
import { auth } from "~/utils/auth";

export default defineEventHandler((event) => {
    const session = await auth.api.getSession({
        headers: event.headers,
    })
});
app/routes/api/index.ts
import { auth } from "./auth";
import { createAPIFileRoute } from "@tanstack/start/api";

export const APIRoute = createAPIFileRoute("/api/$")({
    GET: async ({ request }) => {
        const session = await auth.api.getSession({
            headers: request.headers
        })
    },
});

For more details check session-management documentation.

使用插件

Better Auth 的一大特色是拥有插件生态系统,能够通过少量代码实现复杂的认证功能。

下面示例演示如何使用两步验证插件添加双因素认证。

Server Configuration

To add a plugin, you need to import the plugin and pass it to the plugins option of the auth instance. For example, to add two factor authentication, you can use the following code:

auth.ts
import { betterAuth } from "better-auth"
import { twoFactor } from "better-auth/plugins"

export const auth = betterAuth({
    //...rest of the options
    plugins: [ 
        twoFactor() 
    ] 
})

now two factor related routes and method will be available on the server.

Migrate Database

After adding the plugin, you'll need to add the required tables to your database. You can do this by running the migrate command, or by using the generate command to create the schema and handle the migration manually.

generating the schema:

terminal
npx auth generate

using the migrate command:

terminal
npx auth migrate

If you prefer adding the schema manually, you can check the schema required on the two factor plugin documentation.

Client Configuration

Once we're done with the server, we need to add the plugin to the client. To do this, you need to import the plugin and pass it to the plugins option of the auth client. For example, to add two factor authentication, you can use the following code:

auth-client.ts
import { createAuthClient } from "better-auth/client";
import { twoFactorClient } from "better-auth/client/plugins"; 

const authClient = createAuthClient({
    plugins: [ 
        twoFactorClient({ 
            twoFactorPage: "/two-factor" // the page to redirect if a user needs to verify 2nd factor
        }) 
    ] 
})

now two factor related methods will be available on the client.

profile.ts
import { authClient } from "./auth-client"

const enableTwoFactor = async() => {
    const data = await authClient.twoFactor.enable({
        password // the user password is required
    }) // this will enable two factor
}

const disableTwoFactor = async() => {
    const data = await authClient.twoFactor.disable({
        password // the user password is required
    }) // this will disable two factor
}

const signInWith2Factor = async() => {
    const data = await authClient.signIn.email({
        //...
    })
    //if the user has two factor enabled, it will redirect to the two factor page
}

const verifyTOTP = async() => {
    const data = await authClient.twoFactor.verifyTOTP({
        code: "123456", // the code entered by the user 
        /**
         * If the device is trusted, the user won't
         * need to pass 2FA again on the same device
         */
        trustDevice: true
    })
}