Skip to content

Latest commit

 

History

History
47 lines (26 loc) · 3.41 KB

File metadata and controls

47 lines (26 loc) · 3.41 KB

Authentication

Demo implementation. The auth setup here is intentionally minimal to keep the reference app simple to fork and run. It is not a production-ready auth system. A real deployment should add: email/password or social sign-in, account recovery, session management UX, and CAPTCHA or abuse protection. Supabase Auth supports all of these — this app deliberately omits them to stay focused on the Cloudinary integration.

Overview

Authentication is handled by Supabase Auth via @supabase/ssr. The app uses anonymous (guest) sign-in — no email, no password, no SMTP configuration required. Users get a full Supabase session with a UUID instantly.

Trade-off to document for users: progress is saved in the browser cookie. Clearing cookies creates a new anonymous session with a new UUID; there is no account recovery path. This is intentional — the app is a reference/demo. Forkers who need persistence should add an account-linking flow (Supabase updateUser preserves the UUID).

Production scale note: anonymous sign-ins are rate-limited by Supabase per IP by default. For high-traffic deployments, consider adding CAPTCHA (Supabase Auth supports hCaptcha/Turnstile) and a scheduled cleanup job to delete inactive anonymous users — see the Supabase anonymous auth docs for current guidance on both.

Sign-in flow

  1. User clicks Play as guest at /sign-in.
  2. playAsGuest server action (app/(auth)/sign-in/actions.ts) calls supabase.auth.signInAnonymously().
  3. On success, redirects to /profile.
  4. Profile page checks getProfile() — if no profile row exists yet, redirects to /set-handle.
  5. On failure (e.g. anonymous sign-ins not enabled in dashboard), returns { error: string } displayed on-screen.

Enabling anonymous sign-ins (required)

Anonymous sign-ins must be enabled in the Supabase dashboard for each environment:

Dashboard → Authentication → Sign In / Providers → toggle "Allow anonymous sign-ins"

This is a per-project setting. Enable it for your local dev project and your production project separately.

Session handling

Session cookies are managed by @supabase/ssr. The proxy.ts middleware runs on every request and calls supabase.auth.getClaims() to refresh the session cookie before it expires.

Server Components use lib/supabase/server.ts (cookie-based server client) — session is read from cookies, no round-trip to Supabase on every request.

lib/auth/getSession.ts is a thin helper that calls supabase.auth.getUser() and returns the user or null. All protected pages call this at the top.

Protected routes

app/(protected)/layout.tsx gate-keeps all routes under (protected)/. If no session exists, it redirects to /sign-in. Individual pages may further redirect to /set-handle if the user hasn't created a profile yet.

Handle setup

After signing in as a guest, users must choose a handle (unique lowercase alphanumeric, 1–30 chars). If getProfile() returns null, protected pages redirect to /set-handle. The setHandle action creates a profiles row linked to auth.users. Anonymous users get the same UUID-keyed profile as any other user — all RLS policies work identically.

Sign-out

components/SignOutButton.tsx is a form that calls the signOut server action (app/(auth)/sign-in/actions.ts), which calls supabase.auth.signOut() and redirects to /sign-in.