Combo Auth Plugin
@kardoe/better-auth-combo-auth — Combined magic link and email OTP authentication flow.
@kardoe/better-auth-combo-auth provides a combined authentication flow that sends both a magic link and an OTP code in a single email. Users can click the link (one-click) or enter the 6-digit OTP code — whichever is more convenient.
Installation
npm install @kardoe/better-auth-combo-authServer Setup
Add the plugin to your Better Auth configuration:
import { betterAuth } from "better-auth";
import { comboAuth } from "@kardoe/better-auth-combo-auth";
export const auth = betterAuth({
plugins: [
comboAuth({
sendComboAuth: async ({ email, otp, url }) => {
// Send email with both the magic link (url) and OTP code (otp)
await sendEmail({
to: email,
subject: "Sign in to My App",
html: `
<p>Click the link below to sign in:</p>
<a href="${url}">Sign in to My App</a>
<p>Or enter this code: <strong>${otp}</strong></p>
`,
});
},
}),
],
});Client Usage
import { createAuthClient } from "better-auth/client";
import { comboAuthClient } from "@kardoe/better-auth-combo-auth/client";
const authClient = createAuthClient({
plugins: [comboAuthClient()],
});
// Request authentication — sends email with link + OTP
await authClient.signIn.comboAuth({
email: "user@example.com",
});
// Verify with OTP code (if user enters it manually)
await authClient.signIn.comboAuth({
email: "user@example.com",
otp: "123456",
});How It Works
- User enters their email and requests sign-in
- A single email is sent containing both a magic link and a 6-digit OTP
- Option A: User clicks the magic link — authenticated immediately
- Option B: User enters the OTP code — authenticated after verification
This provides the best of both worlds: convenience of magic links with the reliability of OTP codes (useful when magic links don't work well, e.g., opening email on a different device).
See Also
- Auth Plugins — All authentication plugin options
- Upgrade Anonymous — Convert anonymous sessions to full accounts
- AWS SES — Email delivery for auth flows