Authentication
Last updated on 2026-09-13
The kit uses Supabase Auth for all authentication. Sessions are managed via cookies using @supabase/ssr.
Auth Methods
| Method | Provider | Setup |
|---|---|---|
| Email/password | Built-in | Works out of the box |
| Google OAuth | Google Cloud | Configure in Supabase Dashboard |
| GitHub OAuth | GitHub Apps | Configure in Supabase Dashboard |
| Password reset | Uses Supabase built-in email templates |
Auth Flow
User submits login form
→ Server Action calls supabase.auth.signInWithPassword()
→ Supabase returns session
→ @supabase/ssr sets cookies
→ Middleware reads cookies on next request
→ User is redirected to /dashboard
Auth Actions (lib/actions/auth.ts)
| Action | Parameters | Description |
|---|---|---|
signIn |
email, password | Sign in with email/password |
signUp |
email, password, fullName | Create account; sets full_name in user metadata |
signOut |
-- | Clear session and redirect to /login |
resetPassword |
Send password reset email | |
signInWithProvider |
provider ("google" or "github") |
Redirect to OAuth provider via Supabase Auth |
Middleware (middleware.ts)
The middleware runs on every request and handles:
- Session refresh -- Updates the Supabase session cookie
- Route protection -- Redirects unauthenticated users to
/login - Auth page redirect -- Redirects authenticated users away from
/loginand/register
Public Routes
These routes are accessible without authentication:
/(landing page)/pricing/privacy/terms/login/register/forgot-password
Protected Routes
Everything else requires authentication:
/dashboard,/courses/*,/my-learning,/lessons/*/instructor/*/admin/*- All student, instructor, and admin portal routes
Profile Auto-Creation
When a new user signs up, a database trigger creates their profile:
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger
LANGUAGE plpgsql SECURITY DEFINER
AS $$
BEGIN
INSERT INTO public.profiles (id, email, full_name, avatar_url, role)
VALUES (
new.id,
new.email,
COALESCE(new.raw_user_meta_data->>'full_name', split_part(new.email, '@', 1)),
COALESCE(new.raw_user_meta_data->>'avatar_url', ''),
'student'
);
RETURN new;
END;
$$;
New users are always created with the student role. To make a user an instructor or admin, update their role in the Supabase dashboard.
Role-Based Access
The kit uses three roles enforced via RLS:
| Role | Access | How to assign |
|---|---|---|
student |
Own enrollments, progress, submissions, discussions, messages | Default on signup |
instructor |
Own courses, enrolled students, revenue | Set via Supabase dashboard or admin panel |
admin |
Full access to everything | Set via Supabase dashboard |
OAuth Callback Routes
app/(auth)/auth/callback/route.ts-- Handles the OAuth redirect from providersapp/(auth)/auth/confirm/route.ts-- Handles email confirmation links
Supabase Clients
| Client | Usage | RLS |
|---|---|---|
Server (createClient) |
Auth checks, read queries | Yes (user session) |
Admin (createAdminClient) |
All mutations | No (service role bypasses RLS) |
Browser (createBrowserClient) |
Client-side auth state | Yes (user session) |
Important: All mutations use the admin client (
createAdminClient) to bypass RLS. This ensures operations work regardless of the user's role. The admin client uses theSUPABASE_SERVICE_ROLE_KEYand should never be exposed to the client.