用户和账户

除了用户认证外,Better Auth还提供了一组管理用户的方法。这包括更新用户信息、更改密码等。

用户表存储用户的认证数据点击此处查看模式

用户表可以通过额外字段或插件来扩展,以存储额外的数据。

更新用户

更新用户信息

要更新用户信息,你可以使用客户端提供的 updateUser 函数。updateUser 函数接受一个包含以下属性的对象:

await authClient.updateUser({
    image: "https://example.com/image.jpg",
    name: "John Doe",
})

更改邮箱

要允许用户更改邮箱,首先需要启用 changeEmail 功能,该功能默认是禁用的。将 changeEmail.enabled 设置为 true

export const auth = betterAuth({
    user: {
        changeEmail: {
            enabled: true,
        }
    }
})

对于已验证邮箱的用户,提供 sendChangeEmailVerification 函数。当用户更改邮箱时,此函数会触发,发送包含 URL 和令牌的验证邮件。如果当前邮箱未验证,更改会立即生效,无需验证。

export const auth = betterAuth({
    user: {
        changeEmail: {
            enabled: true,
            sendChangeEmailVerification: async ({ user, newEmail, url, token }, request) => {
                await sendEmail({
                    to: user.email, // 验证邮件必须发送到当前用户邮箱以批准更改
                    subject: '批准邮箱更改',
                    text: `点击链接以批准更改:${url}`
                })
            }
        }
    }
})

启用后,使用客户端的 changeEmail 函数更新用户的邮箱。用户在更改邮箱前必须验证当前邮箱。

await authClient.changeEmail({
    newEmail: "[email protected]",
    callbackURL: "/dashboard", // 验证后重定向
});

验证后,新邮箱会在用户表中更新,并向新地址发送确认邮件。

如果当前邮箱未验证,新邮箱会在没有验证步骤的情况下更新。

更改密码

用户的密码不存储在用户表中,而是存储在账户表中。要更改用户密码,你可以使用客户端提供的 changePassword 函数。changePassword 函数接受一个包含以下属性的对象:

await authClient.changePassword({
    newPassword: "newPassword123",
    currentPassword: "oldPassword123",
    revokeOtherSessions: true, // 撤销用户登录的所有其他会话
});

设置密码

如果用户是使用 OAuth 或其他提供商注册的,他们将没有密码或凭证账户。在这种情况下,你可以使用 setPassword 操作为用户设置密码。出于安全原因,此函数只能从服务器调用。我们建议让用户通过"忘记密码"流程来设置账户密码。

await auth.api.setPassword({
    body: { newPassword: "password" },
    headers: //
});

删除用户

Better Auth 提供了一个从数据库中硬删除用户的工具。默认情况下是禁用的,但你可以通过传递 enabled:true 轻松启用它。

export const auth = betterAuth({
    //...其他配置
    user: {
        deleteUser: { 
            enabled: true
        } 
    }
})

启用后,你可以调用 authClient.deleteUser 从数据库中永久删除用户数据。

添加删除前的验证

为了增加安全性,你可能希望在删除用户账户之前确认用户的意图。常见的方法是发送验证邮件。Better Auth 为此提供了 sendDeleteAccountVerification 工具。

以下是设置方法:

export const auth = betterAuth({
    user: {
        deleteUser: {
            enabled: true,
            sendDeleteAccountVerification: async (
                {
                    user,   // 用户对象
                    url, // 自动生成的删除 URL
                    token  // 验证令牌(可用于生成自定义 URL)
                },
                request  // 原始请求对象(可选)
            ) => {
                // 在此处添加你的邮件发送逻辑
                // 示例:sendEmail(data.user.email, "验证删除", data.url);
            },
        },
    },
});

回调验证的工作原理:

  • 回调 URLsendDeleteAccountVerification 中提供的 URL 是一个预生成的链接,访问时会删除用户数据。
delete-user.ts
await authClient.deleteUser({
    callbackURL: "/goodbye" // 你可以提供一个回调 URL 在删除后重定向
});
  • 认证检查:用户必须登录到他们尝试删除的账户。 如果他们未登录,删除过程将失败。

如果你发送了自定义 URL,你可以使用带有令牌的 deleteUser 方法来删除用户。

delete-user.ts
await authClient.deleteUser({
    token
});

认证要求

要删除用户,用户必须满足以下要求之一:

  1. 有效密码

如果用户有密码,他们可以通过提供密码来删除账户。

delete-user.ts
await authClient.deleteUser({
    password: "password"
});
  1. 新鲜会话

用户必须有一个"新鲜"的会话令牌,意味着用户必须最近登录过。如果未提供密码,则会检查此项。

默认情况下 session.freshAge 设置为 60 * 60 * 24(1 天)。你可以通过向 auth 配置传递 session 对象来更改此值。如果设置为 0,则禁用新鲜度检查。

delete-user.ts
await authClient.deleteUser();
  1. 用户必须提供由 sendDeleteAccountVerification 回调生成的令牌。
delete-user.ts
await authClient.deleteUser({
    token
});

回调

beforeDelete:此回调在用户被删除之前调用。你可以使用此回调在删除用户之前执行任何清理或额外检查。

auth.ts
export const auth = betterAuth({
    user: {
        deleteUser: {
            enabled: true,
            beforeDelete: async (user) => {
                // 在此处执行任何清理或额外检查
            },
        },
    },
});

你也可以抛出 APIError 来中断删除过程。

auth.ts
import { betterAuth } from "better-auth";
import { APIError } from "better-auth/api";
 
export const auth = betterAuth({
    user: {
        deleteUser: {
            enabled: true,
            beforeDelete: async (user, request) => {
                if (user.email.includes("admin")) {
                    throw new APIError("BAD_REQUEST", {
                        message: "管理员账户不能被删除",
                    });
                }
            },
        },
    },
});

afterDelete:此回调在用户被删除后调用。你可以使用此回调在用户被删除后执行任何清理或额外操作。

auth.ts
export const auth = betterAuth({
    user: {
        deleteUser: {
            enabled: true,
            afterDelete: async (user, request) => {
                // 在此处执行任何清理或额外操作
            },
        },
    },
});

账户

Better Auth 支持多种认证方法。每种认证方法称为一个提供商。例如,邮箱和密码认证是一个提供商,Google 认证是一个提供商等。

当用户使用提供商登录时,会为用户创建一个账户。账户存储提供商返回的认证数据。这些数据包括访问令牌、刷新令牌和提供商返回的其他信息。

账户表存储用户的认证数据点击此处查看模式

列出用户账户

要列出用户账户,你可以使用 client.user.listAccounts 方法。这将返回与用户关联的所有账户。

const accounts = await authClient.listAccounts();

账户关联

账户关联使用户能够将多个认证方法与单个账户关联。使用 Better Auth,如果提供商确认用户的邮箱已验证,用户可以将其他社交登录或 OAuth 提供商连接到其现有账户。

如果账户关联被禁用,则无论提供商或邮箱验证状态如何,都不能关联账户。

auth.ts
export const auth = betterAuth({
    account: {
        accountLinking: {
            enabled: true, 
        }
    },
});

强制关联

你可以指定一个"受信任的提供商"列表。当用户使用受信任的提供商登录时,即使提供商未确认邮箱验证状态,他们的账户也会自动关联。请谨慎使用此功能,因为它可能会增加账户被接管的风险。

auth.ts
export const auth = betterAuth({
    account: {
        accountLinking: {
            enabled: true,
            trustedProviders: ["google", "github"]
        }
    },
});

手动关联账户

已登录的用户可以手动将其账户关联到其他社交提供商或基于凭证的账户。

  • 关联社交账户:使用客户端的 user.linkSocial 方法将社交提供商关联到用户的账户。

    await authClient.linkSocial({
        provider: "google", // 要关联的提供商
        callbackURL: "/callback" // 关联完成后回调的 URL
    });

    你还可以在关联社交账户时请求特定的作用域,这些作用域可以与初始认证时使用的作用域不同:

    await authClient.linkSocial({
        provider: "google",
        callbackURL: "/callback",
        scopes: ["https://www.googleapis.com/auth/drive.readonly"] // 请求额外的作用域
    });

    如果你希望用户能够使用与用户不同的邮箱地址关联社交账户,或者如果你想使用不返回邮箱地址的提供商,你需要在账户关联设置中启用此功能。

    auth.ts
    export const auth = betterAuth({
        account: {
            accountLinking: {
                allowDifferentEmails: true
            }
        },
    });
  • 关联基于凭证的账户:要关联基于凭证的账户(例如邮箱和密码),用户可以发起"忘记密码"流程,或者你可以在服务器上调用 setPassword 方法。

    await auth.api.setPassword({
        headers: /* 包含用户会话令牌的标头 */,
        password: /* 新密码 */
    });

出于安全原因,setPassword 不能从客户端调用。

取消账户关联

你可以通过提供 providerId 来取消关联用户账户。

await authClient.unlinkAccount({
    providerId: "google"
});
 
// 取消关联特定账户
await authClient.unlinkAccount({
    providerId: "google",
    accountId: "123"
});

如果账户不存在,它将抛出错误。此外,如果用户只有一个账户,除非 allowUnlinkingAll 设置为 true,否则取消关联过程将失败以防止账户锁定。

auth.ts
export const auth = betterAuth({
    account: {
        accountLinking: {
            allowUnlinkingAll: true
        }
    },
});

On this page