AgentStack
SKILL verified MIT Self-run

Better Auth

skill-fellipeutaka-leon-better-auth · by fellipeutaka

|

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add skill-fellipeutaka-leon-better-auth

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-fellipeutaka-leon-better-auth)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
8d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Better Auth? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Better Auth

Framework-agnostic TypeScript auth library. Plugin-based architecture, 40+ OAuth providers, 18+ framework integrations.

Quick Start

Install

npm install better-auth

Scoped packages (as needed):

| Package | Use case | |---------|----------| | @better-auth/passkey | WebAuthn/Passkey auth | | @better-auth/sso | SAML/OIDC enterprise SSO | | @better-auth/stripe | Stripe payments | | @better-auth/expo | React Native/Expo |

Environment Variables

BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=

Server Config (lib/auth.ts)

import { betterAuth } from "better-auth";

export const auth = betterAuth({
  database: process.env.DATABASE_URL,  // or adapter instance
  emailAndPassword: { enabled: true },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    },
  },
  plugins: [], // add plugins here
});

export type Session = typeof auth.$Infer.Session;

Client Config (lib/auth-client.ts)

import { createAuthClient } from "better-auth/react"; // or /vue, /svelte, /solid, /client

export const authClient = createAuthClient({
  plugins: [], // add client plugins here
});

Route Handler

| Framework | File | Handler | |-----------|------|---------| | Next.js App Router | app/api/auth/[...all]/route.ts | toNextJsHandler(auth) → export { GET, POST } | | Next.js Pages | pages/api/auth/[...all].ts | toNextJsHandler(auth) → default export | | Express | any | app.all("/api/auth/*splat", toNodeHandler(auth)) | | Hono | route | app.on(["POST","GET"], "/api/auth/**", (c) => auth.handler(c.req.raw)) | | SvelteKit | hooks.server.ts | svelteKitHandler({ auth, event }) | | Astro | pages/api/auth/[...all].ts | toAstroHandler(auth) | | Elysia | plugin | new Elysia().mount(auth.handler) |

See [references/framework-integrations.md](references/framework-integrations.md) for all frameworks.

CLI Commands

npx @better-auth/cli@latest migrate          # Apply schema (built-in adapter)
npx @better-auth/cli@latest generate          # Generate for Prisma/Drizzle
npx @better-auth/cli@latest generate --output prisma/schema.prisma
npx @better-auth/cli@latest generate --output src/db/auth-schema.ts

Re-run after adding/changing plugins.

Core Concepts

  • Server instance (auth): handles all auth logic, DB, sessions
  • Client instance (authClient): framework-specific hooks (useSession, signIn, signUp, signOut)
  • Plugins: extend both server and client — add endpoints, DB tables, hooks
  • Type inference: auth.$Infer.Session, auth.$Infer.Session.user for full type safety
  • For separate client/server projects: createAuthClient()

Authentication Methods

| Method | Package | Config/Plugin | Reference | |--------|---------|---------------|-----------| | Email/Password | built-in | emailAndPassword: { enabled: true } | [authentication.md](references/authentication.md) | | Social OAuth | built-in | socialProviders: { google: {...} } | [authentication.md](references/authentication.md) | | Magic Link | built-in | magicLink() plugin | [authentication.md](references/authentication.md) | | Passkey | @better-auth/passkey | passkey() plugin | [authentication.md](references/authentication.md) | | Username | built-in | username() plugin | [authentication.md](references/authentication.md) | | Email OTP | built-in | emailOtp() plugin | [authentication.md](references/authentication.md) | | Phone Number | built-in | phoneNumber() plugin | [authentication.md](references/authentication.md) | | Anonymous | built-in | anonymous() plugin | [authentication.md](references/authentication.md) |

Plugin Quick Reference

Import from dedicated paths for tree-shaking: import { twoFactor } from "better-auth/plugins/two-factor" NOT from "better-auth/plugins".

| Plugin | Server Import | Client Import | Purpose | |--------|---------------|---------------|---------| | twoFactor | better-auth/plugins/two-factor | twoFactorClient | TOTP, OTP, backup codes | | organization | better-auth/plugins/organization | organizationClient | Multi-tenant orgs, teams, RBAC | | admin | better-auth/plugins/admin | adminClient | User management, impersonation | | passkey | @better-auth/passkey | passkeyClient | WebAuthn/FIDO2 | | magicLink | better-auth/plugins/magic-link | magicLinkClient | Passwordless email links | | emailOtp | better-auth/plugins/email-otp | emailOtpClient | Email one-time passwords | | username | better-auth/plugins/username | usernameClient | Username-based auth | | phoneNumber | better-auth/plugins/phone-number | phoneNumberClient | Phone-based auth | | anonymous | better-auth/plugins/anonymous | anonymousClient | Guest sessions | | apiKey | better-auth/plugins/api-key | apiKeyClient | API key management | | bearer | better-auth/plugins/bearer | — | Bearer token auth | | jwt | better-auth/plugins/jwt | jwtClient | JWT tokens | | multiSession | better-auth/plugins/multi-session | multiSessionClient | Multiple active sessions | | oauthProvider | better-auth/plugins/oauth-provider | — | Become OAuth provider | | oidcProvider | better-auth/plugins/oidc-provider | — | Become OIDC provider | | sso | @better-auth/sso | ssoClient | SAML/OIDC enterprise SSO | | openAPI | better-auth/plugins/open-api | — | API documentation | | customSession | better-auth/plugins/custom-session | — | Extend session data | | genericOAuth | better-auth/plugins/generic-oauth | genericOAuthClient | Custom OAuth providers | | oneTap | better-auth/plugins/one-tap | oneTapClient | Google One Tap |

Pattern: server plugin in auth({ plugins: [...] }) + client plugin in createAuthClient({ plugins: [...] }) + re-run CLI migrations.

See [references/plugins.md](references/plugins.md) for detailed usage and custom plugin creation.

Database Setup

| Adapter | Setup | |---------|-------| | SQLite | Pass better-sqlite3 or bun:sqlite instance | | PostgreSQL | Pass pg.Pool instance | | MySQL | Pass mysql2 pool | | Prisma | prismaAdapter(prisma, { provider: "postgresql" }) from better-auth/adapters/prisma | | Drizzle | drizzleAdapter(db, { provider: "pg" }) from better-auth/adapters/drizzle | | MongoDB | mongodbAdapter(db) from better-auth/adapters/mongodb | | Connection string | database: process.env.DATABASE_URL (uses built-in Kysely) |

Critical: Config uses ORM model name, NOT DB table name. Prisma model User mapping to table users → use modelName: "user".

Core schema tables: user, session, account, verification. Plugins add their own tables.

See [references/setup.md](references/setup.md) for full database setup details.

Session Management

Key options:

session: {
  expiresIn: 60 * 60 * 24 * 7,  // 7 days (default)
  updateAge: 60 * 60 * 24,       // refresh every 24h (default)
  freshAge: 60 * 60 * 24,        // require re-auth after 24h for sensitive ops
  cookieCache: {
    enabled: true,
    maxAge: 300,                  // 5 min
    strategy: "compact",          // "compact" | "jwt" | "jwe"
  },
}
  • secondaryStorage (Redis/KV): sessions go there by default, not DB
  • Stateless mode: no DB + cookieCache = session in cookie only
  • customSession plugin: extend session with custom fields

See [references/sessions.md](references/sessions.md) for full session management details.

Security Checklist

| DO | DON'T | |----|-------| | Use 32+ char secret with high entropy | Commit secrets to version control | | Set baseURL with HTTPS in production | Disable CSRF check (disableCSRFCheck) | | Configure trustedOrigins for all frontends | Disable origin check | | Enable rate limiting (on by default in prod) | Use "memory" rate limit storage in serverless | | Configure backgroundTasks.handler on serverless | Skip email verification setup | | Use "jwe" cookie cache for sensitive session data | Store OAuth tokens unencrypted if used for API calls | | Set revokeSessionsOnPasswordReset: true | Return specific error messages ("user not found") |

See [references/security.md](references/security.md) for complete security hardening guide.

Common Gotchas

  1. Model vs table name — config uses ORM model name, not DB table name
  2. Plugin schema — re-run CLI after adding/changing plugins
  3. Secondary storage — sessions go there by default, not DB. Set session.storeSessionInDatabase: true to persist both
  4. Cookie cache — custom session fields NOT cached, always re-fetched from DB
  5. Callback URLs — always use absolute URLs with origin (not relative paths)
  6. Express v5 — use "/api/auth/*splat" not "/api/auth/*" for catch-all routes
  7. Next.js RSC — add nextCookies() plugin to auth config for server component session access

Troubleshooting

| Issue | Fix | |-------|-----| | "Secret not set" | Add BETTER_AUTH_SECRET env var | | "Invalid Origin" | Add domain to trustedOrigins | | Cookies not setting | Check baseURL matches domain; enable secure cookies in prod | | OAuth callback errors | Verify redirect URIs in provider dashboard match exactly | | Type errors after adding plugin | Re-run CLI generate/migrate | | Session null in RSC | Add nextCookies() plugin | | 2FA redirect not working | Add twoFactorClient with onTwoFactorRedirect to client |

Reference Index

| File | When to read | |------|-------------| | [setup.md](references/setup.md) | Setting up new project, configuring DB, route handlers | | [authentication.md](references/authentication.md) | Implementing any auth method (email, social, passkey, magic link, etc.) | | [sessions.md](references/sessions.md) | Configuring session expiry, caching, stateless mode, secondary storage | | [security.md](references/security.md) | Hardening for production — rate limiting, CSRF, cookies, OAuth security | | [plugins.md](references/plugins.md) | Using or creating plugins, plugin catalog | | [framework-integrations.md](references/framework-integrations.md) | Framework-specific setup (Next.js, Nuxt, SvelteKit, Hono, Express, etc.) | | [two-factor.md](references/two-factor.md) | Implementing 2FA (TOTP, OTP, backup codes, trusted devices) | | [organizations.md](references/organizations.md) | Multi-tenant orgs, teams, invitations, RBAC | | [admin.md](references/admin.md) | User management, roles, banning, impersonation | | [hooks-and-middleware.md](references/hooks-and-middleware.md) | Custom logic via before/after hooks, DB hooks, middleware |

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.