Authentication Overview
How Trovella authenticates users via Google OAuth, manages sessions, and handles MCP token-based access.
Trovella uses Better Auth, a self-hosted TypeScript authentication library, with Google OAuth as the sole sign-in method for MVP. All auth data lives in the same Cloud SQL PostgreSQL database as application data -- no separate auth service, no per-user pricing, no vendor lock-in.
How Authentication Works
There are two authentication paths:
Browser sessions use Google OAuth. The user clicks "Continue with Google" on the sign-in page, completes the OAuth consent flow, and Better Auth creates a database-backed session with a cookie. Every subsequent request validates the cookie against the session table. Sessions have a 5-minute cookie cache to reduce database lookups.
MCP requests use Personal Access Tokens (PATs). Users generate a PAT in the dashboard, and MCP clients (like Claude Code) send it as a Bearer token. The token is SHA-256 hashed and validated against the personal_access_token table. PATs are user-scoped, not tenant-scoped.
Auth is Per-Page, Not Middleware
Trovella checks authentication in each server component page, not in Next.js middleware. The middleware handles Content-Security-Policy headers only. This avoids the security risks of middleware-based auth (the March 2025 Next.js middleware vulnerability) and keeps each page's auth requirements explicit:
export default async function Page() {
const session = await getSession();
if (!session) redirect("/auth/sign-in?callbackUrl=/path");
return <DashboardPage session={session}><Content /></DashboardPage>;
}
The DashboardPage server component then calls two idempotent helpers (ensurePersonalOrganization and ensureActiveOrganization) on every render to guarantee the user has a personal org and an active org selected.
Pages in This Topic
ADR-002: Better Auth with Google-Only MVP
The decision record covering why Better Auth was chosen over Clerk, Auth0, Firebase, Auth.js, and Supabase Auth. Covers cost analysis, multi-tenancy requirements, and SSR compatibility.
Sign-In Flow
Step-by-step walkthrough of the Google OAuth flow, from button click through session creation and personal organization bootstrapping.
Session Management
Cookie-based sessions, the 5-minute cache, tRPC context creation with cache bypass, session validation, and sign-out.
Personal Access Tokens
PAT lifecycle (create, validate, revoke), the trov_ prefix convention, SHA-256 hashing, and how MCP requests authenticate.
Package Architecture
The @repo/auth package structure, import conventions, server/client split, and integration points with the web app.
Key Invariants
- All auth goes through Better Auth. No custom session logic.
@repo/authis the only package that importsbetter-auth(enforced by ESLintno-restricted-imports). - Session cookie never leaks to client bundles. Server config is in
@repo/auth/server; client config is in@repo/auth/client. - Feature endpoints use
authorizedProcedure. PAT endpoints are the exception, usingprotectedProcedurebecause PATs are user-scoped, not tenant-scoped. - Google is the MFA provider during social-only MVP. Users who enable 2FA on their Google account get 2FA for Trovella automatically.
Related Topics
- Identity & Access -- Authorization -- how authenticated sessions are turned into CASL abilities
- Identity & Access -- Organizations -- the three-tier organization model that auth bootstraps
- Data & Storage -- Schema Design -- Reference Data -- auth tables classified as global (no RLS)
- Data & Storage -- Query Patterns -- Tenant Context --
withTenantContext()that runs after auth resolves the org - Infrastructure -- Secrets & Configuration -- Environment Variables --
BETTER_AUTH_SECRET,GOOGLE_CLIENT_ID, and other auth env vars