Authentication & Role System
Autofocus implements a sophisticated authentication and authorization system with role-based permissions, subscription tiers, and granular access controls powered by Supabase Auth and PostgreSQL Row Level Security.
🔐 Authentication System
Supabase Auth Integration
Built on Supabase's battle-tested authentication with JWT tokens, OAuth providers, and automatic session management.
Supported Methods
- • Email/Password authentication
- • Google OAuth integration
- • GitHub OAuth integration
- • Email verification required
- • Automatic session refresh
Security Features
- • JWT token-based sessions
- • Secure HTTP-only cookies
- • Automatic token refresh
- • Session timeout handling
- • Rate limiting on auth endpoints
Authentication Flow
1. User signs up/logs in → Supabase Auth
2. JWT token issued → Stored in secure cookie
3. Profile created → Username setup required
4. Role assignment → Default 'basic' subscription
5. Dashboard access → Full platform functionality
👥 Role-Based Permission System
Role Types & Hierarchy
Three distinct role categories: permissions (admin access), subscriptions (feature access), and special roles (program participation).
Permission Roles
admin
Complete platform control
moderator
Content moderation access
Subscription Roles
basic
3 pages, 10 blocks
turbo
10 pages, 50 blocks
summit
Unlimited everything
Special Roles
alpha
Alpha program access
beta
Beta testing features
beta_plus
Enhanced beta access
Permission Matrix
Permission | Admin | Moderator | Summit | Turbo | Basic |
---|---|---|---|---|---|
Admin Panel Access | ✓ | ✗ | ✗ | ✗ | ✗ |
User Management | ✓ | ✓ | ✗ | ✗ | ✗ |
Unlimited Pages | ✓ | ✓ | ✓ | ✗ | ✗ |
Custom Domains | ✓ | ✓ | ✓ | ✗ | ✗ |
Advanced Analytics | ✓ | ✓ | ✓ | ✓ | ✗ |
📊 Resource Limits & Subscription Tiers
Tier Comparison
Feature | Basic (Free) | Turbo ($6.99/mo) | Summit ($16.99/mo) |
---|---|---|---|
Pages | 3 | 10 | Unlimited |
Blocks per Page | 10 | 50 | Unlimited |
Image Upload Size | 1MB | 5MB | 20MB |
Custom Domain | ✗ | ✗ | ✓ |
Analytics | Basic | Advanced | Premium |
Ad Revenue Share | 0% | 50% | 100% |
Resource Limit Implementation
Server-Side Validation
// Check if user has reached limit async function hasReachedLimit(userId, resourceType) { const { data: userSub } = await supabase .rpc('get_subscription_level', { user_id: userId }); const { data: limits } = await supabase .from('resource_limits') .select('max_count') .eq('role_id', userSub.role_id) .eq('resource_type', resourceType) .single(); if (limits.max_count === -1) return false; // Unlimited const { count } = await supabase .from(resourceType === 'page' ? 'pages' : 'content_blocks') .select('*', { count: 'exact' }) .eq('profile_id', userId); return count >= limits.max_count; }
Client-Side Enforcement
// React hook for subscription limits const { subscriptionLevel, hasMinSubscription } = useAuthRoles(); const canCreatePage = useMemo(() => { if (hasMinSubscription('summit')) return true; return pageCount < getPageLimit(subscriptionLevel); }, [subscriptionLevel, pageCount]); // UI state management if (!canCreatePage) { return <UpgradePrompt feature="additional pages" />; }
🛡️ Row Level Security Implementation
Database-Level Security
PostgreSQL RLS policies ensure data security at the database level, preventing unauthorized access even if application logic fails.
User Data Isolation
-- Users can only access their own profile data CREATE POLICY "Users can access own profile" ON profiles FOR ALL USING (id = auth.uid()); -- Users can only modify their own pages CREATE POLICY "Users can manage own pages" ON pages FOR ALL USING (profile_id = auth.uid()); -- Content blocks follow page ownership CREATE POLICY "Users can manage own blocks" ON content_blocks FOR ALL USING ( page_id IN ( SELECT id FROM pages WHERE profile_id = auth.uid() ) );
Public Content Access
-- Public profiles viewable by everyone CREATE POLICY "Public profiles viewable" ON profiles FOR SELECT USING (true); -- Public pages accessible to all CREATE POLICY "Public pages viewable" ON pages FOR SELECT USING (is_public = true); -- Public content blocks visible CREATE POLICY "Public blocks viewable" ON content_blocks FOR SELECT USING ( page_id IN (SELECT id FROM pages WHERE is_public = true) );
Admin Override Policies
-- Admins can access all data for moderation CREATE POLICY "Admins can access all profiles" ON profiles FOR ALL USING ( EXISTS ( SELECT 1 FROM user_roles ur JOIN roles r ON ur.role_id = r.id WHERE ur.user_id = auth.uid() AND r.name = 'admin' ) );
⚛️ React Authentication Context
AuthRolesContext Implementation
React context providing authentication state, role information, and permission checking throughout the application.
Context Provider
export function AuthRolesProvider({ children }) { const [user, setUser] = useState(null); const [roles, setRoles] = useState([]); const [subscriptionLevel, setSubscriptionLevel] = useState('basic'); const [loading, setLoading] = useState(true); // Check if user has specific role const hasRole = (roleName) => { if (roleName === 'admin' && user?.user_metadata?.is_admin) { return true; } return roles.some(role => role.role_name === roleName); }; // Check subscription level const hasMinSubscription = (level) => { const levels = { basic: 0, turbo: 1, summit: 2 }; return levels[subscriptionLevel] >= levels[level]; }; return ( <AuthRolesContext.Provider value={{ user, roles, subscriptionLevel, loading, hasRole, hasMinSubscription }}> {children} </AuthRolesContext.Provider> ); }
Role-Based Components
// Conditional rendering based on roles function AdminPanel() { const { hasRole } = useAuthRoles(); if (!hasRole('admin')) { return <NotAuthorized />; } return <AdminDashboard />; } // Subscription-gated features function PremiumFeature() { const { hasMinSubscription } = useAuthRoles(); if (!hasMinSubscription('turbo')) { return <UpgradePrompt />; } return <AdvancedAnalytics />; }