Files
gh-rafaelcalleja-claude-mar…/skills/better-auth/references/email-password-auth.md
2025-11-30 08:48:52 +08:00

8.4 KiB

Email/Password Authentication

Email/password is built-in auth method in Better Auth. No plugins required for basic functionality.

Server Configuration

Basic Setup

import { betterAuth } from "better-auth";

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    autoSignIn: true, // Auto sign-in after signup (default: true)
    requireEmailVerification: false, // Require email verification before login
    sendResetPasswordToken: async ({ user, url }) => {
      // Send password reset email
      await sendEmail(user.email, url);
    }
  }
});

Custom Password Requirements

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    password: {
      minLength: 8,
      requireUppercase: true,
      requireLowercase: true,
      requireNumbers: true,
      requireSpecialChars: true
    }
  }
});

Client Usage

Sign Up

import { authClient } from "@/lib/auth-client";

const { data, error } = await authClient.signUp.email({
  email: "user@example.com",
  password: "securePassword123",
  name: "John Doe",
  image: "https://example.com/avatar.jpg", // optional
  callbackURL: "/dashboard" // optional
}, {
  onSuccess: (ctx) => {
    // ctx.data contains user and session
    console.log("User created:", ctx.data.user);
  },
  onError: (ctx) => {
    alert(ctx.error.message);
  }
});

Sign In

const { data, error } = await authClient.signIn.email({
  email: "user@example.com",
  password: "securePassword123",
  callbackURL: "/dashboard",
  rememberMe: true // default: true
}, {
  onSuccess: () => {
    // redirect or update UI
  },
  onError: (ctx) => {
    console.error(ctx.error.message);
  }
});

Sign Out

await authClient.signOut({
  fetchOptions: {
    onSuccess: () => {
      router.push("/login");
    }
  }
});

Email Verification

Server Setup

export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ({ user, url, token }) => {
      // Send verification email
      await sendEmail({
        to: user.email,
        subject: "Verify your email",
        html: `Click <a href="${url}">here</a> to verify your email.`
      });
    },
    sendOnSignUp: true, // Send verification email on signup
    autoSignInAfterVerification: true // Auto sign-in after verification
  },
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true // Require verification before login
  }
});

Client Usage

// Send verification email
await authClient.sendVerificationEmail({
  email: "user@example.com",
  callbackURL: "/verify-success"
});

// Verify email with token
await authClient.verifyEmail({
  token: "verification-token-from-email"
});

Password Reset Flow

Server Setup

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    sendResetPasswordToken: async ({ user, url, token }) => {
      await sendEmail({
        to: user.email,
        subject: "Reset your password",
        html: `Click <a href="${url}">here</a> to reset your password.`
      });
    }
  }
});

Client Flow

// Step 1: Request password reset
await authClient.forgetPassword({
  email: "user@example.com",
  redirectTo: "/reset-password"
});

// Step 2: Reset password with token
await authClient.resetPassword({
  token: "reset-token-from-email",
  password: "newSecurePassword123"
});

Change Password (Authenticated)

await authClient.changePassword({
  currentPassword: "oldPassword123",
  newPassword: "newPassword456",
  revokeOtherSessions: true // Optional: logout other sessions
});

Username Authentication

Requires username plugin for username-based auth.

Server Setup

import { betterAuth } from "better-auth";
import { username } from "better-auth/plugins";

export const auth = betterAuth({
  plugins: [
    username({
      // Allow sign in with username or email
      allowUsernameOrEmail: true
    })
  ]
});

Client Setup

import { createAuthClient } from "better-auth/client";
import { usernameClient } from "better-auth/client/plugins";

export const authClient = createAuthClient({
  plugins: [usernameClient()]
});

Client Usage

// Sign up with username
await authClient.signUp.username({
  username: "johndoe",
  password: "securePassword123",
  email: "john@example.com", // optional
  name: "John Doe"
});

// Sign in with username
await authClient.signIn.username({
  username: "johndoe",
  password: "securePassword123"
});

// Sign in with username or email (if allowUsernameOrEmail: true)
await authClient.signIn.username({
  username: "johndoe", // or "john@example.com"
  password: "securePassword123"
});

Framework Setup

Next.js (App Router)

// app/api/auth/[...all]/route.ts
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";

export const { POST, GET } = toNextJsHandler(auth);

Next.js (Pages Router)

// pages/api/auth/[...all].ts
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";

export default toNextJsHandler(auth);

Nuxt

// server/api/auth/[...all].ts
import { auth } from "~/utils/auth";
import { toWebRequest } from "better-auth/utils/web";

export default defineEventHandler((event) => {
  return auth.handler(toWebRequest(event));
});

SvelteKit

// hooks.server.ts
import { auth } from "$lib/auth";
import { svelteKitHandler } from "better-auth/svelte-kit";

export async function handle({ event, resolve }) {
  return svelteKitHandler({ event, resolve, auth });
}

Astro

// pages/api/auth/[...all].ts
import { auth } from "@/lib/auth";

export async function ALL({ request }: { request: Request }) {
  return auth.handler(request);
}

Hono

import { Hono } from "hono";
import { auth } from "./auth";

const app = new Hono();

app.on(["POST", "GET"], "/api/auth/*", (c) => {
  return auth.handler(c.req.raw);
});

Express

import express from "express";
import { toNodeHandler } from "better-auth/node";
import { auth } from "./auth";

const app = express();

app.all("/api/auth/*", toNodeHandler(auth));

Protected Routes

Next.js Middleware

// middleware.ts
import { auth } from "@/lib/auth";
import { NextRequest, NextResponse } from "next/server";

export async function middleware(request: NextRequest) {
  const session = await auth.api.getSession({
    headers: request.headers
  });

  if (!session) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*", "/profile/:path*"]
};

SvelteKit Hooks

// hooks.server.ts
import { auth } from "$lib/auth";
import { redirect } from "@sveltejs/kit";

export async function handle({ event, resolve }) {
  const session = await auth.api.getSession({
    headers: event.request.headers
  });

  if (event.url.pathname.startsWith("/dashboard") && !session) {
    throw redirect(303, "/login");
  }

  return resolve(event);
}

Nuxt Middleware

// middleware/auth.ts
export default defineNuxtRouteMiddleware(async (to) => {
  const { data: session } = await useAuthSession();

  if (!session.value && to.path.startsWith("/dashboard")) {
    return navigateTo("/login");
  }
});

User Profile Management

Get Current User

const { data: session } = await authClient.getSession();
console.log(session.user);

Update User Profile

await authClient.updateUser({
  name: "New Name",
  image: "https://example.com/new-avatar.jpg",
  // Custom fields if defined in schema
});

Delete User Account

await authClient.deleteUser({
  password: "currentPassword", // Required for security
  callbackURL: "/" // Redirect after deletion
});

Best Practices

  1. Password Security: Enforce strong password requirements
  2. Email Verification: Enable for production to prevent spam
  3. Rate Limiting: Prevent brute force attacks (see advanced-features.md)
  4. HTTPS: Always use HTTPS in production
  5. Error Messages: Don't reveal if email exists during login
  6. Session Security: Use secure, httpOnly cookies
  7. CSRF Protection: Better Auth handles this automatically
  8. Password Reset: Set short expiration for reset tokens
  9. Account Lockout: Consider implementing after N failed attempts
  10. Audit Logs: Track auth events for security monitoring