AuthHub - Multi-Tenant Authentication System
A complete authentication and organization management system for Supabase projects. Use this skill when implementing:
- •User signup/signin
- •Organization (tenant) creation
- •Multi-tenant data isolation
- •Team invitations
- •Role-based access control (RBAC)
- •Organization switching
- •Permission management
Explicit Triggers
- •
authhub - •
authentication setup - •
multi-tenant - •
org switching - •
team invitations - •
RBAC - •
tenant management
Quick Start
- •Database Schema: See DATABASE_SCHEMA.md - Run migrations first
- •Supabase Config: See SUPABASE_CONFIG.md - Configure auth settings
- •API Templates: See API_TEMPLATES.md - Copy and customize
- •Frontend Setup: See FRONTEND_SETUP.md - React context and hooks
- •Checklist: See IMPLEMENTATION_CHECKLIST.md - Track progress
Deployment Modes
AuthHub supports two deployment modes. Choose based on your use case:
Mode 1: Standalone App (Most Common)
Use this if: Building a single SaaS product with its own Supabase project.
┌─────────────────────────────────────────────────────────┐ │ Your Supabase Project │ ├─────────────────────────────────────────────────────────┤ │ AuthHub Tables (public schema) │ │ ├── products (your single product entry) │ │ ├── user_profiles │ │ ├── tenants (organizations) │ │ ├── user_tenants │ │ ├── roles (for your product) │ │ └── user_role_assignments │ ├─────────────────────────────────────────────────────────┤ │ Product Tables (public schema with RLS) │ │ ├── customers (has organization_id + RLS) │ │ ├── orders (has organization_id + RLS) │ │ └── ... all your product tables │ └─────────────────────────────────────────────────────────┘
Characteristics:
- •Single Supabase project per product
- •Still uses
productstable (for future central AuthHub integration) - •Product tables in
publicschema withorganization_idcolumn - •RLS policies filter data by organization
- •Queries include
product_idfilter (your single product)
Mode 2: Multi-Product Platform
Use this if: Multiple products share the same Supabase database (like DataSwim + Onboard).
┌─────────────────────────────────────────────────────────┐ │ Shared Supabase Project │ ├─────────────────────────────────────────────────────────┤ │ AuthHub Tables (public schema) │ │ ├── products (DataSwim, Onboard, etc.) │ │ ├── user_profiles │ │ ├── tenants │ │ ├── user_tenants │ │ ├── roles (per product) │ │ └── user_role_assignments (includes product_id) │ ├─────────────────────────────────────────────────────────┤ │ Product A Tables │ Product B Tables │ │ (public or schema) │ (public or schema) │ └─────────────────────────────────────────────────────────┘
Characteristics:
- •Single Supabase project shared by multiple products
- •Each product has unique
product_id - •All queries MUST filter by
product_id - •Enables cross-product features and central management
Future: Central AuthHub Dashboard
By keeping the products table in all deployments, we enable future capabilities:
- •Central dashboard to view all products across the ecosystem
- •API integration to sync product/user data
- •Cross-product analytics and management
- •Single sign-on across products (future feature)
Data Isolation Strategies
Strategy 1: RLS with organization_id (RECOMMENDED)
Best for: Most SaaS applications with fixed schemas.
Every product table includes organization_id and RLS policies:
-- Example: customers table
CREATE TABLE public.customers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES public.tenants(id),
name TEXT NOT NULL,
email TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- RLS Policy
ALTER TABLE public.customers ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can view their org's customers"
ON public.customers FOR SELECT
USING (
organization_id IN (
SELECT tenant_id FROM public.user_tenants
WHERE user_id = auth.uid() AND is_active = true
)
);
Pros:
- •Simple to implement
- •Standard PostgreSQL pattern
- •Easy to query across organizations (for admin dashboards)
- •Works with Supabase's built-in RLS
Cons:
- •All tenants share table structure
- •Large tables may need additional indexing
Strategy 2: Schema-per-tenant (Advanced)
Best for: Applications where tenants define their own data structures (like DataSwim).
Each organization gets its own PostgreSQL schema:
-- Creates: tenant_abc123def456...
SELECT create_tenant_schema('abc123-def4-5678-...');
Pros:
- •Complete data isolation
- •Tenants can have different table structures
- •Easier to export/delete tenant data
Cons:
- •More complex to manage
- •Can't easily query across tenants
- •Schema migrations must run per-tenant
When to use Schema-per-tenant:
- •Users create their own database tables (like DataSwim)
- •Regulatory requirements demand physical data isolation
- •Per-tenant backup/restore requirements
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ Supabase Auth │
│ (auth.users - managed by Supabase) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ public.user_profiles │
│ (extended user info, links to auth.users) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────────────┐
│ public.user_tenants │ │ public.user_role_assignments │
│ (user ↔ org link) │ │ (user ↔ org ↔ product ↔ role)│
└─────────────────────┘ └─────────────────────────────┘
│ │
└─────────────┬─────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ public.tenants │
│ (organizations) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Product Tables (with organization_id) │
│ customers, orders, projects, etc. + RLS policies │
└─────────────────────────────────────────────────────────┘
Key Concepts
1. Product-Scoped Roles
Each product has its own roles tied to a product_id. Even in standalone mode, keep this structure for future compatibility.
2. Junction Tables
NEVER query tenants directly for user access. Always go through:
- •
user_tenants- for user-org membership - •
user_role_assignments- for roles (always filter by product_id)
3. Soft Deletes
All tables use is_active boolean. Never hard delete - set is_active = false.
4. Organization ID in Product Tables
Every product table should have organization_id column with appropriate RLS policies.
5. Always Filter by Product ID
Even in standalone apps, include product_id in queries. This ensures:
- •Consistent patterns across all AuthHub implementations
- •Future compatibility with central management
- •Clean separation if you add another product later
Tech Stack Assumptions
This skill assumes:
- •Framework: Next.js 14/15 with App Router
- •Language: TypeScript
- •Database: Supabase (PostgreSQL)
- •Auth: Supabase Auth
- •Deployment: Netlify, Vercel, or similar
Files in This Skill
| File | Purpose |
|---|---|
| DATABASE_SCHEMA.md | Complete SQL migrations |
| SUPABASE_CONFIG.md | Supabase dashboard settings |
| API_TEMPLATES.md | Next.js API route templates |
| FRONTEND_SETUP.md | React context and components |
| IMPLEMENTATION_CHECKLIST.md | Step-by-step checklist |