Last active
October 6, 2024 10:47
-
-
Save abeisleem/df2dc96744b077a8f6fb6e7d223adab8 to your computer and use it in GitHub Desktop.
An Remix actions & loaders middleware example with Supabase auth
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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({...}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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