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 Email 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 email 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:

  1. Session refresh -- Updates the Supabase session cookie
  2. Route protection -- Redirects unauthenticated users to /login
  3. Auth page redirect -- Redirects authenticated users away from /login and /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 providers
  • app/(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 the SUPABASE_SERVICE_ROLE_KEY and should never be exposed to the client.