Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    augusdogus

    better-auth-best-practices

    augusdogus/better-auth-best-practices
    Productivity
    1
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Skill for integrating Better Auth - the comprehensive TypeScript authentication framework.

    SKILL.md

    Better Auth Integration Guide

    Always consult better-auth.com/docs for code examples and latest API.

    Better Auth is a TypeScript-first, framework-agnostic auth framework supporting email/password, OAuth, magic links, passkeys, and more via plugins.


    Quick Reference

    Environment Variables

    • BETTER_AUTH_SECRET - Encryption secret (min 32 chars). Generate: openssl rand -base64 32
    • BETTER_AUTH_URL - Base URL (e.g., https://example.com)

    Only define baseURL/secret in config if env vars are NOT set.

    File Location

    CLI looks for auth.ts in: ./, ./lib, ./utils, or under ./src. Use --config for custom path.

    CLI Commands

    • npx @better-auth/cli@latest migrate - Apply schema (built-in adapter)
    • npx @better-auth/cli@latest generate - Generate schema for Prisma/Drizzle
    • npx @better-auth/cli mcp --cursor - Add MCP to AI tools

    Re-run after adding/changing plugins.


    Core Config Options

    Option Notes
    appName Optional display name
    baseURL Only if BETTER_AUTH_URL not set
    basePath Default /api/auth. Set / for root.
    secret Only if BETTER_AUTH_SECRET not set
    database Required for most features. See adapters docs.
    secondaryStorage Redis/KV for sessions & rate limits
    emailAndPassword { enabled: true } to activate
    socialProviders { google: { clientId, clientSecret }, ... }
    plugins Array of plugins
    trustedOrigins CSRF whitelist

    Database

    Direct connections: Pass pg.Pool, mysql2 pool, better-sqlite3, or bun:sqlite instance.

    ORM adapters: Import from better-auth/adapters/drizzle, better-auth/adapters/prisma, better-auth/adapters/mongodb.

    Critical: Better Auth uses adapter model names, NOT underlying table names. If Prisma model is User mapping to table users, use modelName: "user" (Prisma reference), not "users".


    Session Management

    Storage priority:

    1. If secondaryStorage defined → sessions go there (not DB)
    2. Set session.storeSessionInDatabase: true to also persist to DB
    3. No database + cookieCache → fully stateless mode

    Cookie cache strategies:

    • compact (default) - Base64url + HMAC. Smallest.
    • jwt - Standard JWT. Readable but signed.
    • jwe - Encrypted. Maximum security.

    Key options: session.expiresIn (default 7 days), session.updateAge (refresh interval), session.cookieCache.maxAge, session.cookieCache.version (change to invalidate all sessions).


    User & Account Config

    User: user.modelName, user.fields (column mapping), user.additionalFields, user.changeEmail.enabled (disabled by default), user.deleteUser.enabled (disabled by default).

    Account: account.modelName, account.accountLinking.enabled, account.storeAccountCookie (for stateless OAuth).

    Required for registration: email and name fields.


    Email Flows

    • emailVerification.sendVerificationEmail - Must be defined for verification to work
    • emailVerification.sendOnSignUp / sendOnSignIn - Auto-send triggers
    • emailAndPassword.sendResetPassword - Password reset email handler

    Security

    In advanced:

    • useSecureCookies - Force HTTPS cookies
    • disableCSRFCheck - ⚠️ Security risk
    • disableOriginCheck - ⚠️ Security risk
    • crossSubDomainCookies.enabled - Share cookies across subdomains
    • ipAddress.ipAddressHeaders - Custom IP headers for proxies
    • database.generateId - Custom ID generation or "serial"/"uuid"/false

    Rate limiting: rateLimit.enabled, rateLimit.window, rateLimit.max, rateLimit.storage ("memory" | "database" | "secondary-storage").


    Hooks

    Endpoint hooks: hooks.before / hooks.after - Array of { matcher, handler }. Use createAuthMiddleware. Access ctx.path, ctx.context.returned (after), ctx.context.session.

    Database hooks: databaseHooks.user.create.before/after, same for session, account. Useful for adding default values or post-creation actions.

    Hook context (ctx.context): session, secret, authCookies, password.hash()/verify(), adapter, internalAdapter, generateId(), tables, baseURL.


    Plugins

    Import from dedicated paths for tree-shaking:

    import { twoFactor } from "better-auth/plugins/two-factor"
    

    NOT from "better-auth/plugins".

    Popular plugins: twoFactor, organization, passkey, magicLink, emailOtp, username, phoneNumber, admin, apiKey, bearer, jwt, multiSession, sso, oauthProvider, oidcProvider, openAPI, genericOAuth.

    Client plugins go in createAuthClient({ plugins: [...] }).


    Client

    Import from: better-auth/client (vanilla), better-auth/react, better-auth/vue, better-auth/svelte, better-auth/solid.

    Key methods: signUp.email(), signIn.email(), signIn.social(), signOut(), useSession(), getSession(), revokeSession(), revokeSessions().


    Type Safety

    Infer types: typeof auth.$Infer.Session, typeof auth.$Infer.Session.user.

    For separate client/server projects: createAuthClient<typeof auth>().


    Common Gotchas

    1. Model vs table name - Config uses ORM model name, not DB table name
    2. Plugin schema - Re-run CLI after adding plugins
    3. Secondary storage - Sessions go there by default, not DB
    4. Cookie cache - Custom session fields NOT cached, always re-fetched
    5. Stateless mode - No DB = session in cookie only, logout on cache expiry
    6. Change email flow - Sends to current email first, then new email

    Resources

    • Docs
    • Options Reference
    • LLMs.txt
    • GitHub
    • Init Options Source
    Recommended Servers
    Astro Docs
    Astro Docs
    Vercel Grep
    Vercel Grep
    Cloudflare
    Cloudflare
    Repository
    augusdogus/junkyard-index
    Files