Skip to content

[Auth] Harden Authentication — Social OAuth (GitHub + Google) + RBAC with Better Auth #10

Description

@hasnaintypes

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.tssocialProviders 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

  • Add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET to .env.example with instructions
  • Uncomment socialProviders in convex/auth/helpers.ts (lines 91–103)
  • Uncomment handleSocialSignIn in SignInForm.tsx and SignUpForm.tsx
  • Add OAuth buttons (Google) to both sign-in and sign-up forms
  • Verify account linking works (same email, different provider) — already enabled via accountLinking.enabled: true
  • Test redirect flow: /sign-in → provider → /dashboard

2. Role-Based Access Control (RBAC)

  • Add role field to the user table schema: v.optional(v.union(v.literal("admin"), v.literal("member"))) — default to "member" on creation
  • Install Better Auth admin plugin in convex/auth/helpers.ts
  • Add a requireRole(ctx, role) helper in convex/lib/ that reads the session user and throws ConvexError if unauthorized
  • Wrap admin-only Convex mutations (e.g., bulk operations, usage resets) with the role check
  • Add organization plugin (Better Auth) for future team/workspace support — schema only, no UI yet

3. Route-Level Authorization (Next.js Middleware)

  • Create src/middleware.ts using getToken() to protect /dashboard, /campaigns, /settings routes
  • Redirect unauthenticated requests to /sign-in
  • Add plan-based guards: read plan field from session and gate pro-only routes (e.g., /sequences) with an upgrade prompt

4. Security Hardening

  • Verify trustedOrigins in createAuthOptions is locked to SITE_URL only (already set, confirm no wildcard fallback)
  • Confirm rate limit config (window: 60, max: 10) is sufficient for sign-in brute-force protection
  • Add stricter rate limit for password reset endpoint specifically

Acceptance Criteria

  • User can sign in with Google on both sign-in and sign-up pages
  • Account linking works when the same email exists across providers
  • role field exists on all new users, defaults to "member"
  • Admin-only mutations reject non-admin callers with a ConvexError
  • Unauthenticated requests to auth-required routes redirect to /sign-in
  • No GOOGLE_CLIENT_SECRET ever reaches the client bundle

References

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions