LogoBoring Template

Authentication

Learn how to implement and configure authentication using Better-auth in your application.

Authentication System

This template uses Better-auth for authentication, providing a modern, secure multi-provider authentication solution.

Key Features

Multiple Providers

🔐 Support for Google, GitHub, Apple, Magic Link, and Email/Password

Passwordless

📧 Email magic links authentication for password-free login

Security

🛡️ Rate limiting protection to prevent abuse

Multiple Sessions

🔄 Robust session management across devices

Server-Side

⚡ Authentication helpers for server components

Account Linking

🔗 Link accounts using OAuth providers

Setup Guide

1. Environment Variables

Create or update your .env.local file:

.env.local
# Better-auth configuration
BETTER_AUTH_URL=http://localhost:3000
BETTER_AUTH_SECRET=your_secret_key
 
# Google OAuth
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
 
# Github OAuth
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
 
# Email (Resend)
RESEND_API_KEY=your_resend_api_key
RESEND_EMAIL=your_email@domain.com

Remember to generate a strong secret key for BETTER_AUTH_SECRET and never commit your .env.local file to version control.

2. Auth Configuration

Set up your authentication configuration in lib/auth.ts:

lib/auth.ts
import { db } from "@/server/db/config/database";
import { account, sessions, users, verification } from "@/server/db/schemas";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from "better-auth/next-js";
import { magicLink } from "better-auth/plugins";
 
import { configuration } from "@/lib/config";
import { resend } from "@/lib/resend";
import { MagicLinkMail } from "@/components/auth/magic-link-mail";
 
export const auth = betterAuth({
  appName: "Boring Template",
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: {
      user: users,
      session: sessions,
      account: account,
      verification: verification,
    },
  }),
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID || "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
    },
  },
  account: {
    accountLinking: {
      enabled: true,
      trustedProviders: ["google", "email-password"],
    },
  },
 
  rateLimit: {
    storage: "database",
    modelName: "ratelimit",
  },
 
  plugins: [
    magicLink({
      sendMagicLink: async ({ email, url }) => {
        const result = await resend.emails.send({
          from: process.env.RESEND_EMAIL!,
          to: email,
          subject: `Magic Login Link from ${configuration.site.name}!`,
          react: MagicLinkMail({
            email: email,
            magicLinkMail: url,
          }),
        });
        if (result.error) {
          throw new Error(result.error?.message);
        }
      },
    }),
    nextCookies(),
  ],
});

Usage Examples

Better-auth makes it easy to protect routes, API endpoints, and check authentication status throughout your application.

Protected API Routes

Route Handler
import { auth } from "@/lib/auth";
 
export async function GET() {
  const session = await auth();
  if (!session) {
    return new Response("Unauthorized", { status: 401 });
  }
  // Your protected API logic
}

Protected Pages

Server Component
import { auth } from "@/lib/auth";
 
export default async function ProtectedPage() {
  const session = await auth();
  if (!session) {
    redirect("/sign-in");
  }
  return <div>Protected Content</div>;
}

Getting Current User

import { headers } from "next/headers";
 
import { auth } from "@/lib/auth";
 
export async function getCurrentUser() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });
 
  if (session) {
    // User is authenticated
    console.log(session.user.email);
  }
}

Security Features

Rate Limiting

Protection against brute force attacks and abuse:

const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(5, "1 m"),
});

Best Practices

Environment Variables

  • Never commit sensitive credentials
  • Use different values for development and production
  • Regularly rotate secrets

Security

  • Keep dependencies updated
  • Implement proper CORS policies
  • Use HTTPS in production
  • Enable rate limiting

User Experience

  • Provide clear error messages
  • Implement proper loading states
  • Add remember me functionality
  • Support multiple auth methods

Additional Resources

On this page