Security

Authentication and authorization

Use sessions, loader guards, and application roles safely.

Session clients

Each request creates one Supabase SSR client. Loaders and actions share it through React Router context, while outgoing auth cookies accumulate on the final response.

Protecting routes

Call requireUser at the beginning of every authenticated loader and action. Administration actions must call requireAdmin before creating a service-role client.

typescript
1export async function action({ context, request }: Route.ActionArgs) { 2 const user = await requireUser(context); 3 const formData = await request.formData(); 4 5 // Validate the form and mutate only data the user can access. 6 return { userId: user.id, formData }; 7}

Authorization boundaries

Row Level Security remains the primary authorization boundary for user actions. Service-role operations are reserved for trusted server flows and must derive identity or permissions from a verified session, never from form fields.

Workspace roles

Workspace roles control application capabilities, while database policies enforce the same tenant boundary. Treat a hidden button as presentation, not authorization.

Still stuck? Share feedback about the documentation.