| name | better-auth |
| description | Comprehensive authentication skill for Better Auth with TypeScript, Next.js 16, and JWT tokens. Use when implementing authentication systems with Better Auth, setting up Next.js App Router integration, or configuring JWT token authentication. |
Better Auth Authentication Skill
This skill provides comprehensive knowledge for implementing authentication systems using Better Auth with TypeScript, Next.js 16, and JWT tokens.
Overview
Better Auth is a framework-agnostic authentication and authorization library for TypeScript that provides enterprise-grade features through a flexible plugin architecture. It handles everything from basic email/password authentication to advanced features like JWT tokens, OAuth, and session management.
Core Setup
Backend Configuration
import { betterAuth } from "better-auth";
import { jwt } from "better-auth/plugins";
export const auth = betterAuth({
database: {
provider: "postgresql", // or your preferred database
url: process.env.DATABASE_URL!,
},
secret: process.env.BETTER_AUTH_SECRET!,
plugins: [
jwt({
algorithm: "HS256",
expiresIn: "7d",
issuer: "https://example.com",
audience: ["https://api.example.com"],
}),
],
emailAndPassword: {
enabled: true,
},
emailVerification: {
enabled: true,
},
});
Next.js Integration
Create lib/auth.ts:
import { auth } from "./auth";
// Export for use throughout the application
export { auth };
Next.js 16 App Router Integration
Server Component Authentication
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
export default async function ProtectedPage() {
const session = await auth.api.getSession({
headers: await headers(),
});
if (!session) {
redirect("/sign-in");
}
return (
<div>
<h1>Protected Content</h1>
<p>Welcome, {session.user.name}!</p>
</div>
);
}
Middleware for Route Protection
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
export async function middleware(request: NextRequest) {
const session = await auth.api.getSession({
headers: await headers()
});
if (!session && request.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/sign-in", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*"],
};
JWT Token Implementation
Server-Side JWT Configuration
import { betterAuth } from "better-auth";
import { jwt } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
jwt({
algorithm: "HS256",
expiresIn: "7d",
issuer: "https://example.com",
audience: ["https://api.example.com"],
}),
],
});
Client-Side JWT Usage
import { createAuthClient } from "better-auth/client";
import { jwtClient } from "better-auth/client/plugins";
const authClient = createAuthClient({
plugins: [jwtClient()],
});
// Generate JWT
const { data } = await authClient.jwt.generate();
console.log("JWT:", data.token);
// Decode JWT
const decoded = await authClient.jwt.decode({
token: data.token,
});
console.log("JWT payload:", decoded);
Bearer Token Authentication
Server Configuration
import { betterAuth } from "better-auth";
import { bearer } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
bearer({
expiresIn: 60 * 60 * 24 * 7, // 7 days
}),
],
});
Client Usage
import { bearerClient } from "better-auth/client/plugins";
const authClient = createAuthClient({
plugins: [bearerClient()],
});
// Generate Bearer Token
const { data } = await authClient.bearer.generate();
console.log("Access token:", data.accessToken);
// Use Bearer Token in API Calls
fetch("/api/protected", {
headers: {
Authorization: `Bearer ${data.accessToken}`,
},
});
API Route Protection
Protected API Route
import { auth } from "@/lib/auth";
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await auth.api.getSession({
headers: {
authorization: req.headers.authorization,
},
});
if (!session) {
return res.status(401).json({ error: "Unauthorized" });
}
// Process protected route
res.status(200).json({ message: "Access granted", user: session.user });
}
Email and Password Authentication
import { betterAuth } from 'better-auth';
export const auth = betterAuth({
database: {
provider: "postgresql",
url: process.env.DATABASE_URL!,
},
secret: process.env.BETTER_AUTH_SECRET!,
emailVerification: {
sendEmailVerification: async (user) => {
// Implement your email verification logic here
}
},
emailAndPassword: {
enabled: true,
requireEmailVerification: false, // Set to true if email verification is required
}
});
Client-Side Integration
Creating Auth Client
import { createAuthClient } from "better-auth/client";
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000",
fetchOptions: {
credentials: "include",
},
});
Using in Client Components
"use client";
import { useState } from "react";
import { authClient } from "@/lib/auth-client";
export function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const response = await authClient.signIn.email({
email,
password,
callbackURL: "/dashboard",
});
if (response.error) {
console.error(response.error);
}
} catch (error) {
console.error("Sign in error:", error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Sign In</button>
</form>
);
}
Environment Variables
DATABASE_URL=your_database_connection_string
BETTER_AUTH_SECRET=your_secret_key
NEXT_PUBLIC_BASE_URL=http://localhost:3000
Best Practices
- Always use environment variables for secrets
- Validate sessions server-side for protected content
- Use Next.js middleware for route-level protection
- Implement proper error handling
- Configure JWT expiration based on security requirements
- Use HTTPS in production
- Regularly rotate secrets