Documentation
Documentation
Introduction

Getting Started

Getting StartedInstallationQuick StartProject Structure

Architecture

Architecture OverviewTech StacktRPC MiddlewareDesign Principles

Patterns

Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

DatabaseSchema DefinitionDatabase OperationsMigrationsCaching

API

tRPCProceduresRouterstRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

StorageConfigurationUsageBuckets

Configuration

ConfigurationEnvironment VariablesFeature Flags

Templates

Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate tRPC RouterAdd Translations

Development

DevelopmentCommandsAI AgentsBest Practices

Configuration

Configure authentication settings

Auth Configuration

Configure authentication settings in src/config/app.ts:

export const AuthConfig = {
  cookiePrefix: "auth",
  disableOpenAPI: false,
  disableCookieCache: false,
  storeSessionInDatabase: false,
  disableSessionRefresh: false,
  sessionFreshAge: 0,
  disableAccountDeletion: false,
  signUpAutoLogin: false,
} as const;

Configuration Options

OptionTypeDefaultDescription
cookiePrefixstring"auth"Prefix for auth cookies
disableOpenAPIbooleanfalseDisable OpenAPI/REST endpoints
disableCookieCachebooleanfalseDisable cookie-based session caching
storeSessionInDatabasebooleanfalseStore sessions in database (stateful)
disableSessionRefreshbooleanfalseDisable automatic session refresh
sessionFreshAgenumber0Age (seconds) for fresh sessions
disableAccountDeletionbooleanfalseDisable account deletion
signUpAutoLoginbooleanfalseAuto-login after registration

Environment Variables

Required Variables

# Better-Auth secret (minimum 32 characters)
BETTER_AUTH_SECRET="your-secret-key-min-32-chars"

# Application URL
BETTER_AUTH_URL="http://localhost:3000"

OAuth Providers (Optional)

Google OAuth

GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"

Get Google OAuth credentials

  1. Go to Google Cloud Console
  2. Create a new project or select existing
  3. Enable Google+ API
  4. Go to Credentials → Create OAuth 2.0 Client ID
  5. Add authorized redirect URI: https://your-app.com/api/auth/callback/google

GitHub OAuth

GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"

Get GitHub OAuth credentials

  1. Go to GitHub Settings → Developer settings
  2. OAuth Apps → New OAuth App
  3. Add Authorization callback URL: https://your-app.com/api/auth/callback/github
  4. Copy Client ID and Client Secret

Session Storage

JWT Sessions (Default)

Stateless sessions stored in cookies:

export const AuthConfig = {
  storeSessionInDatabase: false, // Default
};

Pros:

  • No database queries for session validation
  • Scales horizontally
  • Fast performance

Cons:

  • Cannot revoke sessions (must wait for expiry)
  • Larger cookie size

Database Sessions

Stateful sessions stored in database:

export const AuthConfig = {
  storeSessionInDatabase: true,
};

Pros:

  • Can revoke sessions immediately
  • Smaller cookie size
  • More control over active sessions

Cons:

  • Database query on every request
  • Requires database connection

Session Freshness

Require recent authentication for sensitive operations:

export const AuthConfig = {
  sessionFreshAge: 300, // 5 minutes in seconds
};

In your procedure, check if session is fresh:

if (ctx.session.fresh === false) {
  throw new TRPCError({
    code: "FORBIDDEN",
    message: "Please re-authenticate",
  });
}

Security Best Practices

1. Use Strong Secrets

# Generate a secure secret
openssl rand -base64 32

2. Enable HTTPS in Production

BETTER_AUTH_URL="https://your-app.com"

3. Configure CORS

In src/lib/auth/server.ts, configure allowed origins:

cors: {
  origin: ["https://your-app.com"],
  credentials: true,
}

4. Rate Limit Auth Endpoints

Auth procedures should use the "AUTH" rate limit:

login: publicProcedure
  .meta({ rateLimit: "AUTH" })
  .mutation(/* ... */),

5. Implement Password Requirements

password: z.string()
  .min(8, "At least 8 characters")
  .regex(/[A-Z]/, "Must contain uppercase")
  .regex(/[0-9]/, "Must contain number")
  .regex(/[^A-Za-z0-9]/, "Must contain special character"),

Troubleshooting

Session Not Persisting

  • Check BETTER_AUTH_SECRET is set and consistent across deployments
  • Verify BETTER_AUTH_URL matches your domain
  • Check cookie settings for secure/sameSite attributes
  • Clear cookies and try again

OAuth Redirect Issues

  • Verify callback URLs in provider settings exactly match
  • Check BETTER_AUTH_URL environment variable
  • Ensure HTTPS in production
  • Check browser console for errors

Database Connection Errors

  • Verify database credentials in .env
  • Check database is running
  • Run migrations: pnpm db:push

Next Steps

Session Management

OAuth Providers

Environment Config

On this page

Auth Configuration
Configuration Options
Environment Variables
Required Variables
OAuth Providers (Optional)
Google OAuth
Get Google OAuth credentials
GitHub OAuth
Get GitHub OAuth credentials
Session Storage
JWT Sessions (Default)
Database Sessions
Session Freshness
Security Best Practices
1. Use Strong Secrets
2. Enable HTTPS in Production
3. Configure CORS
4. Rate Limit Auth Endpoints
5. Implement Password Requirements
Troubleshooting
Session Not Persisting
OAuth Redirect Issues
Database Connection Errors
Next Steps