上次登录方式
跟踪并显示用户最后使用的身份验证方式
上次登录方式插件用于跟踪用户最近一次使用的身份验证方式(邮箱、OAuth 提供商等)。这使您能够在登录页面上显示有用的指示标志,例如“上次使用 Google 登录”,或根据用户偏好优先显示某些登录方式。
安装
将插件添加到您的身份验证配置
import { betterAuth } from "better-auth"
import { lastLoginMethod } from "better-auth/plugins"
export const auth = betterAuth({
// ... other config options
plugins: [
lastLoginMethod()
]
})将客户端插件添加到您的身份验证客户端
import { createAuthClient } from "better-auth/client"
import { lastLoginMethodClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
lastLoginMethodClient()
]
})使用方法
安装后,插件会自动跟踪用户最后一次使用的身份验证方式。您可以在应用程序中检索并显示该信息。
获取最后使用的方式
客户端插件提供了多个方法来操作最后登录的方式:
import { authClient } from "@/lib/auth-client"
// 获取最后使用的登录方式
const lastMethod = authClient.getLastUsedLoginMethod()
console.log(lastMethod) // "google", "email", "github" 等等
// 检查某种方式是否为最后使用
const wasGoogle = authClient.isLastUsedLoginMethod("google")
// 清除存储的登录方式
authClient.clearLastUsedLoginMethod()UI 集成示例
下面展示如何使用该插件增强登录页面:
import { authClient } from "@/lib/auth-client"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
export function SignInPage() {
const lastMethod = authClient.getLastUsedLoginMethod()
return (
<div className="space-y-4">
<h1>登录</h1>
{/* 邮箱登录 */}
<div className="relative">
<Button
onClick={() => authClient.signIn.email({...})}
variant={lastMethod === "email" ? "default" : "outline"}
className="w-full"
>
使用邮箱登录
{lastMethod === "email" && (
<Badge className="ml-2">上次使用</Badge>
)}
</Button>
</div>
{/* OAuth 提供商 */}
<div className="relative">
<Button
onClick={() => authClient.signIn.social({ provider: "google" })}
variant={lastMethod === "google" ? "default" : "outline"}
className="w-full"
>
使用 Google 登录
{lastMethod === "google" && (
<Badge className="ml-2">上次使用</Badge>
)}
</Button>
</div>
<div className="relative">
<Button
onClick={() => authClient.signIn.social({ provider: "github" })}
variant={lastMethod === "github" ? "default" : "outline"}
className="w-full"
>
使用 GitHub 登录
{lastMethod === "github" && (
<Badge className="ml-2">上次使用</Badge>
)}
</Button>
</div>
</div>
)
}数据库持久化
默认情况下,最后登录方式仅存储在 cookie 中。若需更持久的跟踪和分析,可以启用数据库存储。
启用数据库存储
在插件配置中将 storeInDatabase 设置为 true:
import { betterAuth } from "better-auth"
import { lastLoginMethod } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
lastLoginMethod({
storeInDatabase: true
})
]
})访问数据库字段
启用数据库存储后,lastLoginMethod 字段将在用户对象中可用:
import { auth } from "@/lib/auth"
// 服务器端访问
const session = await auth.api.getSession({ headers })
console.log(session?.user.lastLoginMethod) // "google", "email", 等等
// 通过会话进行客户端访问
const { data: session } = authClient.useSession()
console.log(session?.user.lastLoginMethod)数据库模式
启用 storeInDatabase 后,插件会在 user 表中添加如下字段:
表:user
自定义模式配置
你可以自定义数据库字段名:
import { betterAuth } from "better-auth"
import { lastLoginMethod } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
lastLoginMethod({
storeInDatabase: true,
schema: {
user: {
lastLoginMethod: "last_auth_method" // 自定义字段名
}
}
})
]
})配置选项
上次登录方式插件接受以下选项:
服务端选项
import { betterAuth } from "better-auth"
import { lastLoginMethod } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
lastLoginMethod({
// Cookie 配置
cookieName: "better-auth.last_used_login_method", // 默认: "better-auth.last_used_login_method"
maxAge: 60 * 60 * 24 * 30, // 默认: 30 天,单位秒
// 数据库存储
storeInDatabase: false, // 默认: false
// 自定义方式解析
customResolveMethod: (ctx) => {
// 自定义逻辑决定登录方式
if (ctx.path === "/oauth/callback/custom-provider") {
return "custom-provider"
}
// 返回 null 使用默认解析
return null
},
// 模式定制 (启用 storeInDatabase 时)
schema: {
user: {
lastLoginMethod: "custom_field_name"
}
}
})
]
})cookieName: string
- 用于存储最后登录方式的 Cookie 名称
- 默认:
"better-auth.last_used_login_method" - 注意: 该 Cookie 设置为
httpOnly: false,以便客户端 JavaScript 访问用于 UI 功能
maxAge: number
- Cookie 过期时间(秒)
- 默认:
2592000(30 天)
storeInDatabase: boolean
- 是否将最后登录方式存储在数据库中
- 默认:
false - 启用时,会在用户表中添加
lastLoginMethod字段
customResolveMethod: (ctx: GenericEndpointContext) => string | null
- 用于从请求上下文中确定登录方式的自定义函数
- 返回
null使用默认解析逻辑 - 对自定义 OAuth 提供程序或身份验证流程很有用
schema: object
- 启用
storeInDatabase时自定义数据库字段名 - 允许将
lastLoginMethod字段映射到自定义列名
客户端选项
import { createAuthClient } from "better-auth/client"
import { lastLoginMethodClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
lastLoginMethodClient({
cookieName: "better-auth.last_used_login_method" // 默认: "better-auth.last_used_login_method"
})
]
})cookieName: string
- 用于读取最后登录方式的 Cookie 名称
- 必须与服务端的
cookieName配置匹配 - 默认:
"better-auth.last_used_login_method"
默认方式解析
插件默认跟踪以下身份验证方式:
- Email authentication:
"email" - OAuth providers: Provider ID(例如
"google","github","discord") - OAuth2 callbacks: URL 路径中的提供程序 ID
- Sign up methods: 与登录方式相同
插件自动从以下端点检测方式:
/callback/:id- 带有提供程序 ID 的 OAuth 回调/oauth2/callback/:id- 带有提供程序 ID 的 OAuth2 回调/sign-in/email- 邮箱登录/sign-up/email- 邮箱注册
跨域支持
插件会自动继承 Better Auth 集中 Cookie 系统的 Cookie 设置,解决了最后登录方式无法在以下情况下持久化的问题:
- 跨子域设置:
auth.example.com→app.example.com - 跨源设置:
api.company.com→app.different.com
当在 Better Auth 配置中启用 crossSubDomainCookies 或 crossOriginCookies 时,插件会自动使用与会话 Cookie 相同的域、secure 和 sameSite 设置,确保应用中的一致行为。
高级示例
自定义提供商跟踪
如果你有自定义的 OAuth 提供程序或身份验证方式,可以使用 customResolveMethod 选项:
import { betterAuth } from "better-auth"
import { lastLoginMethod } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
lastLoginMethod({
customResolveMethod: (ctx) => {
// 跟踪自定义 SAML 提供商
if (ctx.path === "/saml/callback") {
return "saml"
}
// 跟踪 magic link 验证
if (ctx.path === "/magic-link/verify") {
return "magic-link"
}
// 跟踪手机身份验证
if (ctx.path === "/sign-in/phone") {
return "phone"
}
// 返回 null 使用默认逻辑
return null
}
})
]
})与 Expo 一起使用
使用 Better Auth 配合 Expo 时,请确保从 @better-auth/expo/plugins 而非 better-auth/plugins/client 导入客户端插件。这确保最后登录方式能正确存储到配置的存储中。
import { createAuthClient } from "better-auth/react"
import { expoClient } from "@better-auth/expo"
import { lastLoginMethodClient } from "@better-auth/expo/plugins"
import * as SecureStore from "expo-secure-store"
export const authClient = createAuthClient({
plugins: [
expoClient({
scheme: "myapp",
storagePrefix: "myapp",
storage: SecureStore,
}),
lastLoginMethodClient({
storagePrefix: "myapp",
storage: SecureStorage,
})
]
})仅在 Expo 应用中使用(不需要浏览器支持时),可以省略服务端插件,仅依赖客户端插件。