From 5d3a3dddcde0b98e11ed072f1114f01a68c6c4d9 Mon Sep 17 00:00:00 2001 From: Jon Meyers Date: Sat, 29 Oct 2022 21:44:03 +1100 Subject: [PATCH 1/5] docs: add docs for remix auth helpers --- .../docs/guides/auth/auth-helpers/remix.mdx | 881 ++++++++++++++++++ 1 file changed, 881 insertions(+) create mode 100644 apps/reference/docs/guides/auth/auth-helpers/remix.mdx diff --git a/apps/reference/docs/guides/auth/auth-helpers/remix.mdx b/apps/reference/docs/guides/auth/auth-helpers/remix.mdx new file mode 100644 index 00000000000..7596e258640 --- /dev/null +++ b/apps/reference/docs/guides/auth/auth-helpers/remix.mdx @@ -0,0 +1,881 @@ +--- +id: remix +title: Supabase Auth with Remix +description: Authentication helpers for loaders and actions in Remix. +sidebar_label: 'Remix' +--- + +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' + +This submodule provides convenience helpers for implementing user authentication in Remix applications. + +## Install the Remix helper library + + + + + +```sh +npm install @supabase/auth-helpers-remix +``` + +This library supports the following tooling versions: + +- Remix: `>=1.7.2` + + + + +```sh +yarn add @supabase/auth-helpers-remix +``` + +This library supports the following tooling versions: + +- Remix: `>=1.7.2` + +## Set up environment variables + +Retrieve your project URL and anon key in your project's [API settings](https://app.supabase.com/project/_/settings/api) in the Dashboard to set up the following environment variables. For local development you can set them in a `.env` file. See an [example](https://github.com/supabase/auth-helpers/blob/main/examples/remix/.env.example). + +```bash title=".env" +SUPABASE_URL=YOUR_SUPABASE_URL +SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY +``` + +## Loader + + + + +Loader functions run on the server immediately before the component is rendered. They respond to all GET requests on a route. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { json } from '@remix-run/node'; // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix'; + +export const loader = async ({ request }) => { + const response = new Response(); + // an empty response is required for the auth helpers + // to set cookies to manage auth + + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ); + + const { data } = await supabaseClient.from('test').select('*'); + + // in order for the set-cookie header to be set, + // headers must be returned as part of the loader response + return json( + { data }, + { + headers: response.headers + } + ); +}; +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Loader` function. + + + + +Loader functions run on the server immediately before the component is rendered. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { LoaderFunction, json } from '@remix-run/node'; // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix'; + +export const loader: LoaderFunction = async ({ + request +}: { + request: Request +}) => { + const response = new Response(); + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ); + + const { data } = await supabaseClient.from('test').select('*'); + + return json( + { data }, + { + headers: response.headers + } + ); +}; +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Loader` function. + + + + +## Action + + + + +Action functions run on the server and respond to HTTP requests to a route, other than GET - POST, PUT, PATCH, DELETE etc. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { json } from '@remix-run/node'; // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix'; + +export const action = async ({ request }) => { + const response = new Response(); + + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ); + + const { data } = await supabaseClient.from('test').select('*'); + + return json( + { data }, + { + headers: response.headers + } + ); +}; +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Action` function. + + + + +Action functions run on the server and respond to HTTP requests to a route, other than GET - POST, PUT, PATCH, DELETE etc. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { ActionFunction, json } from '@remix-run/node'; // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix'; + +export const action: ActionFunction = async ({ + request +}: { + request: Request +}) => { + const response = new Response(); + + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ); + + const { data } = await supabaseClient.from('test').select('*'); + + return json( + { data }, + { + headers: response.headers + } + ); +}; +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Action` function. + + + + +## Session and User + +You can determine if a user is authenticated by checking their session using the `getSession` function. + +```jsx +const { data: { session }} = await supabaseClient.auth.getSession(); +``` + +The session contains a user property. + +```jsx +const user = session?.user; +``` + +> This is the recommended way for accessing the logged in user. There is also a `getUser()` function but this does not refresh the session if it has expired. + +## Client-side + + + + +In order to use the Supabase client in the browser - fetching data in `useEffect` or subscribing to realtime events - we need to do a little more plumbing. Remix does not include a way to make environment variables available to the browser, so we need to pipe them through from a `loader` function in our `root.jsx` route and attach them to the `window`. + +```jsx title="app/root.jsx" +export const loader = () => { + const { SUPABASE_URL, SUPABASE_ANON_KEY } = process.env; + return json({ + env: { + SUPABASE_URL, + SUPABASE_ANON_KEY + } + }); +}; +``` + +> These may not be stored in `process.env` for environments other than Node. + +Next, we call the `useLoaderData` hook in our component to get the `env` object. + +```jsx title="app/root.jsx" +const { env } = useLoaderData(); +``` + +And then, add a `