Complete Google OAuth authentication system with Supabase, featuring role-based access control, remember me functionality, and secure session management.
- Single Sign-On with Google accounts
- Secure token management
- Automatic session refresh
- Users choose role (Founder/Investor) before first login
- Role is permanently locked to account
- Cannot switch roles without new account
- Role mismatch detection prevents unauthorized access
- Optional "Remember me for 30 days" checkbox
- Auto-login on return visits if enabled
- Expiry tracked in database
- Automatic logout when expired
- Row Level Security (RLS) on user data
- JWT token validation
- Automatic session refresh
- Secure logout functionality
- All main pages require authentication
- Role-based route protection
- Automatic redirect to login if unauthorized
- Loading states during auth checks
frontend/lib/supabase.ts- Supabase client & auth functionsfrontend/app/login/page.tsx- Login page with role selectionfrontend/app/auth/callback/page.tsx- OAuth callback handlerfrontend/contexts/AuthContext.tsx- Global auth state managementfrontend/components/Auth/ProtectedRoute.tsx- Route protection wrappersupabase_schema.sql- Database schemaSUPABASE_SETUP.md- Setup instructionsfrontend/.env.local.example- Environment variables template
frontend/app/providers.tsx- Added AuthProviderfrontend/app/page.tsx- Redirect logic based on authfrontend/app/chat/page.tsx- Protected route implementationfrontend/components/Layout/Header.tsx- Logout functionalityfrontend/package.json- Added @supabase/supabase-js dependency
user_profiles table:
- id (UUID, primary key, references auth.users)
- email (TEXT, not null)
- role (TEXT, 'founder' or 'investor')
- full_name (TEXT, optional)
- remember_me (BOOLEAN, default false)
- remember_me_expires (TIMESTAMPTZ, nullable)
- created_at (TIMESTAMPTZ)
- updated_at (TIMESTAMPTZ)1. User visits /login
2. Selects role (Founder/Investor)
3. Clicks "Continue with Google"
4. Optionally checks "Remember me for 30 days"
5. Redirected to Google OAuth
6. Returns to /auth/callback
7. Profile created with selected role
8. Redirected to /chat
1. User visits site
2. AuthContext checks session
3. Validates remember_me_expires
4. If valid → Auto-login → /chat
5. If expired → Clear session → /login
1. User visits site
2. No valid session found
3. Redirected to /login
1. User logs in with existing account
2. System checks stored role vs. selected role
3. If mismatch → Logout → Error message
4. User must use correct role or different email
- Users can only view their own profile
- Users can only update their own profile
- Enforced at database level- Tokens validated on every request
- Automatic refresh before expiry
- Secure storage in localStorage
- HttpOnly cookies for sensitive data
- Role checked on route access
- Protected API endpoints (backend)
- Cannot switch roles without new account
- Database constraint prevents invalid roles
cd frontend
npm installFollow detailed instructions in SUPABASE_SETUP.md
Create frontend/.env.local:
NEXT_PUBLIC_SUPABASE_URL=your_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_key
NEXT_PUBLIC_API_URL=http://localhost:8000Execute supabase_schema.sql in Supabase SQL Editor
Configure in Supabase Authentication settings
npm run dev-
First Login:
- Go to
/login - Choose Founder or Investor
- Sign in with Google
- Check "Remember me" to stay logged in for 30 days
- Go to
-
Using the App:
- All main pages are protected
- Role-specific navigation and features
- Logout button in header
-
Logging Out:
- Click logout icon in header
- Session cleared
- Redirected to login
- Protecting Routes:
import ProtectedRoute from '@/components/Auth/ProtectedRoute';
export default function MyPage() {
return (
<ProtectedRoute allowedRoles={['founder']}>
<YourContent />
</ProtectedRoute>
);
}- Accessing User Info:
import { useAuth } from '@/contexts/AuthContext';
function MyComponent() {
const { session, profile, signOut } = useAuth();
return (
<div>
<p>Role: {profile?.role}</p>
<p>Email: {profile?.email}</p>
<button onClick={signOut}>Logout</button>
</div>
);
}- Checking Auth State:
const { session, profile, loading } = useAuth();
if (loading) return <Loader />;
if (!session) return <LoginPrompt />;
if (profile.role !== 'founder') return <Unauthorized />;- Can select founder role and login
- Can select investor role and login
- Remember me enables auto-login
- Remember me expires after 30 days
- Cannot access app without login
- Cannot switch roles with same account
- Role mismatch shows error
- Logout works correctly
- Session persists on page refresh
- Protected routes redirect to login
- Role-based navigation works
Solution: Run npm install in frontend directory
Solution: Check .env.local has correct Supabase URL
Solution: Verify redirect URI in Google Cloud Console
Solution: Check remember_me is enabled and not expired
Solution: User trying to login with different role - must use correct role or new email
Consider implementing:
- Email/password authentication option
- Password reset flow
- Email verification
- Two-factor authentication
- Social login with other providers
- Admin panel for user management
- Activity logging