Skip to content

Instantly share code, notes, and snippets.

@abeisleem
Last active October 6, 2024 10:47
Show Gist options
  • Save abeisleem/df2dc96744b077a8f6fb6e7d223adab8 to your computer and use it in GitHub Desktop.
Save abeisleem/df2dc96744b077a8f6fb6e7d223adab8 to your computer and use it in GitHub Desktop.
An Remix actions & loaders middleware example with Supabase auth
import {
ActionFunction,
DataFunctionArgs,
LoaderFunction,
redirect,
} from "@remix-run/cloudflare";
import {
createServerClient,
parseCookieHeader,
serializeCookieHeader,
} from "@supabase/ssr";
import { createClient } from "@supabase/supabase-js";
import { getSession } from "./session";
type FunctionArgs = DataFunctionArgs & {
user: User | null;
supabaseClient: SupabaseClient;
};
type WithAuthReturnType =
| ReturnType<LoaderFunction>
| ReturnType<ActionFunction>;
const withAuth =
(
fn: (args: FunctionArgs) => WithAuthReturnType,
{ required = true }: { required?: boolean } = {}
) =>
async (context: DataFunctionArgs) => {
// If using @supabase/supabase-js
const session = await getSession(context.request.headers.get("Cookie"));
const accessToken = session.get("accessToken");
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
global: {
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
});
// If using @supabase/ssr
const supabase = createServerClient(
SUPABASE_URL,
SUPABASE_ANON_KEY,
{
cookies: {
getAll() {
return parseCookieHeader(request.headers.get("Cookie") ?? "");
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
headers.append(
"Set-Cookie",
serializeCookieHeader(name, value, options)
)
);
},
},
});
const { user } = await supabase.auth.getUser(accessToken);
if (!user && required) {
throw redirect("/login");
}
return fn({
...context,
user,
supabaseClient: supabase,
});
};
export default withAuth;
/////////////
// Usage
////////////
export const action = withAuth(async ({ supabaseClient, user, request }, { required: true }) => {
// ...
const { data, error } = await supabase.from('rows').select();
});
export const loader = withAuth(async ({ supabaseClient, params, request }, { required: false }) => {
// ...
const { data, error } = await supabase.from('rows').insert({...});
});
import { createCookieSessionStorage } from "@remix-run/cloudflare";
const { getSession, commitSession, destroySession } =
createCookieSessionStorage({
cookie: {
name: "sb:token",
maxAge: 60 * 59,
path: "/",
sameSite: "lax",
httpOnly: true,
secure: true,
secrets: ["supabase is the dopest!"],
},
});
export { getSession, commitSession, destroySession };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment