Overview
The auth layer is scaffolded with Better Auth + Convex but social providers and role-based access control are both stubbed out. This issue covers enabling them properly.
Current State
convex/auth/helpers.ts — socialProviders block is commented out; env vars needed
src/components/auth/SignInForm.tsx — social sign-in buttons are commented out
- No
role field on the user table
- No authorization middleware on Convex mutations/queries
- No route-level guards beyond the
ClientAuthBoundary
- Better Auth
admin and organization plugins are not installed
Tasks
1. Enable Google OAuth
2. Role-Based Access Control (RBAC)
3. Route-Level Authorization (Next.js Middleware)
4. Security Hardening
Acceptance Criteria
References
Overview
The auth layer is scaffolded with Better Auth + Convex but social providers and role-based access control are both stubbed out. This issue covers enabling them properly.
Current State
convex/auth/helpers.ts—socialProvidersblock is commented out; env vars neededsrc/components/auth/SignInForm.tsx— social sign-in buttons are commented outrolefield on theusertableClientAuthBoundaryadminandorganizationplugins are not installedTasks
1. Enable Google OAuth
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRETto.env.examplewith instructionssocialProvidersinconvex/auth/helpers.ts(lines 91–103)handleSocialSignIninSignInForm.tsxandSignUpForm.tsxaccountLinking.enabled: true/sign-in→ provider →/dashboard2. Role-Based Access Control (RBAC)
rolefield to theusertable schema:v.optional(v.union(v.literal("admin"), v.literal("member")))— default to"member"on creationadminplugin inconvex/auth/helpers.tsrequireRole(ctx, role)helper inconvex/lib/that reads the session user and throwsConvexErrorif unauthorizedorganizationplugin (Better Auth) for future team/workspace support — schema only, no UI yet3. Route-Level Authorization (Next.js Middleware)
src/middleware.tsusinggetToken()to protect/dashboard,/campaigns,/settingsroutes/sign-inplanfield from session and gate pro-only routes (e.g.,/sequences) with an upgrade prompt4. Security Hardening
trustedOriginsincreateAuthOptionsis locked toSITE_URLonly (already set, confirm no wildcard fallback)window: 60, max: 10) is sufficient for sign-in brute-force protectionAcceptance Criteria
rolefield exists on all new users, defaults to"member"ConvexError/sign-inGOOGLE_CLIENT_SECRETever reaches the client bundleReferences
convex/auth/helpers.ts— main auth config, lines 89–103 (commented social providers)src/components/auth/SignInForm.tsx— lines 60, 127–133 (commented social UI)convex/users/schema.ts— user table definition