# Email/Password Authentication
Email/password is built-in auth method in Better Auth. No plugins required for basic functionality.
## Server Configuration
### Basic Setup
```ts
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
```ts
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
password: {
minLength: 8,
requireUppercase: true,
requireLowercase: true,
requireNumbers: true,
requireSpecialChars: true
}
}
});
```
## Client Usage
### Sign Up
```ts
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
```ts
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
```ts
await authClient.signOut({
fetchOptions: {
onSuccess: () => {
router.push("/login");
}
}
});
```
## Email Verification
### Server Setup
```ts
export const auth = betterAuth({
emailVerification: {
sendVerificationEmail: async ({ user, url, token }) => {
// Send verification email
await sendEmail({
to: user.email,
subject: "Verify your email",
html: `Click here 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
```ts
// 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
```ts
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
sendResetPasswordToken: async ({ user, url, token }) => {
await sendEmail({
to: user.email,
subject: "Reset your password",
html: `Click here to reset your password.`
});
}
}
});
```
### Client Flow
```ts
// 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)
```ts
await authClient.changePassword({
currentPassword: "oldPassword123",
newPassword: "newPassword456",
revokeOtherSessions: true // Optional: logout other sessions
});
```
## Username Authentication
Requires `username` plugin for username-based auth.
### Server Setup
```ts
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
```ts
import { createAuthClient } from "better-auth/client";
import { usernameClient } from "better-auth/client/plugins";
export const authClient = createAuthClient({
plugins: [usernameClient()]
});
```
### Client Usage
```ts
// 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)
```ts
// 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)
```ts
// pages/api/auth/[...all].ts
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export default toNextJsHandler(auth);
```
### Nuxt
```ts
// 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
```ts
// 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
```ts
// pages/api/auth/[...all].ts
import { auth } from "@/lib/auth";
export async function ALL({ request }: { request: Request }) {
return auth.handler(request);
}
```
### Hono
```ts
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
```ts
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
```ts
// 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
```ts
// 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
```ts
// 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
```ts
const { data: session } = await authClient.getSession();
console.log(session.user);
```
### Update User Profile
```ts
await authClient.updateUser({
name: "New Name",
image: "https://example.com/new-avatar.jpg",
// Custom fields if defined in schema
});
```
### Delete User Account
```ts
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