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 />;
}