Falsafa
FrontendHigh-Level Design

Auth Flow

Three-layer auth architecture: edge middleware, server-side helper, client-side context. Supabase Auth with SSR cookies, role-based access, blocked-user enforcement, and debug mode bypass.

Auth is implemented in three layers that each serve a different purpose: the edge middleware guards routes, the server helper provides user data to pages and API routes, and the client context drives the UI.

Debug mode

When NEXT_PUBLIC_DEBUG_MODE=true, all three layers are bypassed. The middleware allows every route, auth() returns a mock admin user, and the client context shows a fully authenticated session. This is the development escape hatch.

Layer 1: Edge Middleware

middleware.ts runs on every request (except static assets). It is the first line of defense:

  1. If DEBUG_MODE is set, every request is allowed immediately.
  2. If NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_ANON_KEY is missing, only public routes are allowed.
  3. Otherwise, it creates a Supabase SSR client and calls getUser().
  4. If the user is authenticated but their profile status is blocked, they are redirected to /auth/login?error=blocked.
  5. If the route is not in the public list and the user is not authenticated, they are redirected to /auth/login?error=unauthenticated.
  6. If the route is an auth page (/auth/...) and the user is already authenticated, they are redirected to /library.

The public route list covers: home, category, book detail, all auth pages, settings, library, chat, wishlist, search, help, notifications, upload-book, and checkout.

Layer 2: Server Helper

auth() in auth.ts is the canonical way for pages and API routes to get the current user:

  1. Creates an SSR Supabase client and calls getUser().
  2. Uses the admin client (service-role key) to query profiles (display name, status, email) and user_roles (role) - bypassing RLS so that cookie token restrictions don't interfere.
  3. If the profile status is blocked, returns null.
  4. Returns a { user } object with id, email, displayName, role, and status.

The same pattern is available through getAuthUser() and requireAuth() in lib/auth-middleware.ts, which wraps the Supabase call with the same debug-mode escape hatch.

The admin client uses SUPABASE_SERVICE_ROLE_KEY with a fallback to NEXT_PUBLIC_SUPABASE_ANON_KEY, so privileged queries work even when the service key is unset in development.

Layer 3: Client Context

use-auth.tsx provides the <AuthProvider> component and the useAuth() hook:

  1. On mount, calls supabase.auth.getUser() and fetches /api/auth/me for role/status enrichment.
  2. Subscribes to Supabase onAuthStateChange to re-check on login or logout.
  3. Exposes through context: user, isLoading, isAuthenticated, isAdmin, isStaff, role, status, logout(), and refresh().

Pages check isAuthenticated and isAdmin to show or hide UI elements. The admin panel uses useAdminAuth() which redirects to /library if the user is not an admin.

Registration Flow

Sign-up is a server action (actions.ts:register):

  1. Validates fields (min length six for password, name min length two).
  2. Calls supabase.auth.signUp() with display_name in user metadata.
  3. On success, inserts a row into profiles with the user's ID, email, and display name.
  4. Returns 'success' or an error message string.

Authorization Model

Authorization is role-based using the user_roles table:

RoleAccess
userAuthenticated pages (library, chat, wishlist, upload, settings)
moderatorUser access + comment moderation, report management
adminEverything, including admin panel, user management, settings

Role checks happen at the server level using the admin client (to avoid RLS issues in server actions). The client context also exposes isAdmin and isStaff booleans for UI conditional rendering.

Blocked Users

Blocked users are enforced at two levels:

  • Middleware: immediately redirects blocked users to login with a ?error=blocked param.
  • Server helper: auth() returns null for blocked users, preventing any API call from succeeding.

There is no client-side block enforcement - the middleware and server layers ensure blocked users cannot reach any authenticated route or execute any privileged operation.

On this page