diff --git a/apps/reference/_auth_helpers/next-js.md b/apps/reference/_auth_helpers/next-js.md index e9f6990506c..3cc90c70794 100644 --- a/apps/reference/_auth_helpers/next-js.md +++ b/apps/reference/_auth_helpers/next-js.md @@ -20,6 +20,7 @@ npm install @supabase/auth-helpers-react ``` Using [yarn](https://yarnpkg.com/): + ```sh yarn add @supabase/auth-helpers-nextjs @@ -54,9 +55,9 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key The path to your dynamic API route file would be `/pages/api/auth/[...supabase].js`. Populate that file as follows: ```js -import { handleAuth } from '@supabase/auth-helpers-nextjs'; +import { handleAuth } from '@supabase/auth-helpers-nextjs' -export default handleAuth({ logout: { returnTo: '/' } }); +export default handleAuth({ logout: { returnTo: '/' } }) ``` Executing `handleAuth()` creates the following route handlers under the hood that perform different parts of the authentication flow: @@ -71,16 +72,16 @@ Wrap your `pages/_app.js` component with the `UserProvider` component: ```jsx // pages/_app.js -import React from 'react'; -import { UserProvider } from '@supabase/auth-helpers-react'; -import { supabaseClient } from '@supabase/auth-helpers-nextjs'; +import React from 'react' +import { UserProvider } from '@supabase/auth-helpers-react' +import { supabaseClient } from '@supabase/auth-helpers-nextjs' export default function App({ Component, pageProps }) { return ( - ); + ) } ``` @@ -91,23 +92,23 @@ You can now determine if a user is authenticated by checking that the `user` obj For [row level security](https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security) to work properly when fetching data client-side, you need to make sure to import the `{ supabaseClient }` from `# @supabase/auth-helpers-nextjs` and only run your query once the user is defined client-side in the `useUser()` hook: ```js -import { Auth } from '@supabase/ui'; -import { useUser } from '@supabase/auth-helpers-react'; -import { supabaseClient } from '@supabase/auth-helpers-nextjs'; -import { useEffect, useState } from 'react'; +import { Auth } from '@supabase/ui' +import { useUser } from '@supabase/auth-helpers-react' +import { supabaseClient } from '@supabase/auth-helpers-nextjs' +import { useEffect, useState } from 'react' const LoginPage = () => { - const { user, error } = useUser(); - const [data, setData] = useState(); + const { user, error } = useUser() + const [data, setData] = useState() useEffect(() => { async function loadData() { - const { data } = await supabaseClient.from('test').select('*'); - setData(data); + const { data } = await supabaseClient.from('test').select('*') + setData(data) } // Only run query once user is logged in. - if (user) loadData(); - }, [user]); + if (user) loadData() + }, [user]) if (!user) return ( @@ -120,7 +121,7 @@ const LoginPage = () => { socialButtonSize="xlarge" /> - ); + ) return ( <> @@ -130,10 +131,10 @@ const LoginPage = () => {

client-side data fetching with RLS

{JSON.stringify(data, null, 2)}
- ); -}; + ) +} -export default LoginPage; +export default LoginPage ``` ### Server-side rendering (SSR) - withPageAuth @@ -142,13 +143,13 @@ If you wrap your `getServerSideProps` with `withPageAuth` your props object will ```js // pages/profile.js -import { withPageAuth } from '@supabase/auth-helpers-nextjs'; +import { withPageAuth } from '@supabase/auth-helpers-nextjs' export default function Profile({ user }) { - return
Hello {user.name}
; + return
Hello {user.name}
} -export const getServerSideProps = withPageAuth({ redirectTo: '/login' }); +export const getServerSideProps = withPageAuth({ redirectTo: '/login' }) ``` If there is no authenticated user, they will be redirect to your home page, unless you specify the `redirectTo` option. @@ -158,20 +159,20 @@ user props. You can also access the user session data by calling `getUser` insid ```js // pages/protected-page.js -import { withPageAuth, getUser } from '@supabase/auth-helpers-nextjs'; +import { withPageAuth, getUser } from '@supabase/auth-helpers-nextjs' export default function ProtectedPage({ user, customProp }) { - return
Protected content
; + return
Protected content
} export const getServerSideProps = withPageAuth({ redirectTo: '/foo', async getServerSideProps(ctx) { // Access the user object - const { user, accessToken } = await getUser(ctx); - return { props: { email: user?.email } }; - } -}); + const { user, accessToken } = await getUser(ctx) + return { props: { email: user?.email } } + }, +}) ``` ### Server-side data fetching with RLS @@ -182,15 +183,15 @@ For [row level security](https://supabase.com/docs/learn/auth-deep-dive/auth-row import { User, withPageAuth, - supabaseServerClient -} from '@supabase/auth-helpers-nextjs'; + supabaseServerClient, +} from '@supabase/auth-helpers-nextjs' export default function ProtectedPage({ user, - data + data, }: { user: User, - data: any + data: any, }) { return ( <> @@ -198,17 +199,17 @@ export default function ProtectedPage({
{JSON.stringify(data, null, 2)}
{JSON.stringify(user, null, 2)}
- ); + ) } export const getServerSideProps = withPageAuth({ redirectTo: '/', async getServerSideProps(ctx) { // Run queries with RLS on the server - const { data } = await supabaseServerClient(ctx).from('test').select('*'); - return { props: { data } }; - } -}); + const { data } = await supabaseServerClient(ctx).from('test').select('*') + return { props: { data } } + }, +}) ``` ### Server-side data fetching to OAuth APIs using `provider_token` @@ -216,7 +217,7 @@ export const getServerSideProps = withPageAuth({ When using third-party auth providers, sessions are initiated with an additional `provider_token` field which is persisted as an HTTPOnly cookie upon logging in to enabled usage on the server side. The `provider_token` can be used to make API requests to the OAuth provider's API endpoints on behalf of the logged-in user. In the following example, we fetch the user's full profile from the third-party API during SSR using their id and auth token: ```js -import { User, withPageAuth, getUser } from '@supabase/auth-helpers-nextjs'; +import { User, withPageAuth, getUser } from '@supabase/auth-helpers-nextjs' interface Profile { /* ... */ @@ -224,33 +225,33 @@ interface Profile { export default function ProtectedPage({ user, - data + data, }: { user: User, - profile: Profile + profile: Profile, }) { - return
Protected content
; + return
Protected content
} export const getServerSideProps = withPageAuth({ redirectTo: '/', async getServerSideProps(ctx) { // Retrieve provider_token from cookies - const provider_token = ctx.req.cookies['sb-provider-token']; + const provider_token = ctx.req.cookies['sb-provider-token'] // Get logged in user's third-party id from metadata - const { user } = await getUser(ctx); - const userId = user?.user_metadata.provider_id; + const { user } = await getUser(ctx) + const userId = user?.user_metadata.provider_id const profile: Profile = await ( await fetch(`https://api.example.com/users/${userId}`, { method: 'GET', headers: { - Authorization: `Bearer ${provider_token}` - } + Authorization: `Bearer ${provider_token}`, + }, }) - ).json(); - return { props: { profile } }; - } -}); + ).json() + return { props: { profile } } + }, +}) ``` ## Protecting API routes @@ -262,16 +263,16 @@ Wrap an API Route to check that the user has a valid session. If they're not log // pages/api/protected-route.js import { withApiAuth, - supabaseServerClient -} from '@supabase/auth-helpers-nextjs'; + supabaseServerClient, +} from '@supabase/auth-helpers-nextjs' export default withApiAuth(async function ProtectedRoute(req, res) { // Run queries with RLS on the server const { data } = await supabaseServerClient({ req, res }) .from('test') - .select('*'); - res.json(data); -}); + .select('*') + res.json(data) +}) ``` If you visit `/api/protected-route` without a valid session cookie, you will get a 401 response. @@ -282,25 +283,24 @@ As an alternative to protecting individual pages using `getServerSideProps` with ```ts // pages/protected/_middleware.ts -import { withMiddlewareAuth } from '@supabase/auth-helpers-nextjs/middleware'; +import { withMiddlewareAuth } from '@supabase/auth-helpers-nextjs/middleware' -export const middleware = withMiddlewareAuth({ redirectTo: '/login' }); +export const middleware = withMiddlewareAuth({ redirectTo: '/login' }) ``` It is also possible to add finer granularity based on the user logged in. I.e. you can specify a promise to determine if a specific user has permission or not. - ```ts // pages/protected/_middleware.ts -import { withMiddlewareAuth } from '@supabase/auth-helpers-nextjs/dist/middleware'; +import { withMiddlewareAuth } from '@supabase/auth-helpers-nextjs/dist/middleware' -export const middleware = withMiddlewareAuth({ +export const middleware = withMiddlewareAuth({ redirectTo: '/login', authGuard: { isPermitted: async (user) => user.email?.endsWith('@example.com') ?? false, - redirectTo: '/insufficient-permissions' - } -}); + redirectTo: '/insufficient-permissions', + }, +}) ``` ## Migrating from @supabase/supabase-auth-helpers to @supabase/auth-helpers @@ -312,4 +312,4 @@ This is a step by step guide on migrating away from the `@supabase/supabase-auth 3. Replace all imports of `@supabase/supabase-auth-helpers/react` in your project with `@supabase/auth-helpers-react`. 4. Replace all instances of `withAuthRequired` in any of your NextJS pages with `withPageAuth`. 5. Replace all instances of `withAuthRequired` in any of your NextJS API endpoints with `withApiAuth`. -6. Uninstall `@supabase/supabase-auth-helpers`. \ No newline at end of file +6. Uninstall `@supabase/supabase-auth-helpers`. diff --git a/apps/reference/_auth_helpers/svelte-kit.md b/apps/reference/_auth_helpers/svelte-kit.md index 65fcfc7525f..0b868d560eb 100644 --- a/apps/reference/_auth_helpers/svelte-kit.md +++ b/apps/reference/_auth_helpers/svelte-kit.md @@ -20,6 +20,7 @@ npm install @supabase/auth-helpers-svelte ``` Using [yarn](https://yarnpkg.com/): + ```sh yarn add @supabase/auth-helpers-sveltekit @@ -49,14 +50,14 @@ We will start off by creating a `db.ts` file inside of our `src/lib` directory. ```ts // src/lib/db.ts -import { createSupabaseClient } from '@supabase/auth-helpers-sveltekit'; +import { createSupabaseClient } from '@supabase/auth-helpers-sveltekit' const { supabaseClient } = createSupabaseClient( import.meta.env.VITE_SUPABASE_URL as string, import.meta.env.VITE_SUPABASE_ANON_KEY as string -); +) -export { supabaseClient }; +export { supabaseClient } ``` Edit your `__layout.svelte` file and add import the `SupaAuthHelper` component, the `supabaseClient` we just instantiated and the `session` store. @@ -64,15 +65,15 @@ Edit your `__layout.svelte` file and add import the `SupaAuthHelper` component, ```html // src/routes/__layout.svelte -```` +``` ### Hooks setup @@ -80,18 +81,18 @@ Our `hooks.ts` file is where the heavy lifting of this library happens, we need ```ts // src/hooks.ts -import { handleAuth } from '@supabase/auth-helpers-sveltekit'; -import type { GetSession, Handle } from '@sveltejs/kit'; -import { sequence } from '@sveltejs/kit/hooks'; +import { handleAuth } from '@supabase/auth-helpers-sveltekit' +import type { GetSession, Handle } from '@sveltejs/kit' +import { sequence } from '@sveltejs/kit/hooks' -export const handle: Handle = sequence(...handleAuth()); +export const handle: Handle = sequence(...handleAuth()) export const getSession: GetSession = async (event) => { - const { user, accessToken, error } = event.locals; - return { - user, - accessToken, - error + const { user, accessToken, error } = event.locals + return { + user, + accessToken, + error, } } ``` @@ -103,6 +104,7 @@ These will create the handlers under the hood that perform different parts of th - `/api/auth/logout`: You can logout the user. ### Typings + In order to get the most out of TypeScript and its intellisense, you should import our types into the `app.d.ts` type definition file that comes with your SvelteKit project. ```ts @@ -111,19 +113,15 @@ In order to get the most out of TypeScript and its intellisense, you should impo // See https://kit.svelte.dev/docs/types#app // for information about these interfaces declare namespace App { -  interface UserSession { -    user: import('@supabase/supabase-js').User; -    accessToken?: string; -  } -  -  interface Locals extends UserSession { -    error: import('@supabase/supabase-js').ApiError; -  } + interface UserSession { + user: import('@supabase/supabase-js').User + accessToken?: string + } + interface Locals extends UserSession { + error: import('@supabase/supabase-js').ApiError + } -  interface Session extends UserSession {} - -  // interface Platform {} -  // interface Stuff {} + interface Session extends UserSession {} // interface Platform {} // interface Stuff {} } ``` @@ -144,9 +142,11 @@ In your `src/hooks.ts` file the logout handler is already setup and you can conf > By default the redirect path after logging out will be `/`. ```ts -export const handle = sequence(...handleAuth({ - logout: { returnTo: '/auth/signin' } -})); +export const handle = sequence( + ...handleAuth({ + logout: { returnTo: '/auth/signin' }, + }) +) ``` ### Basic Setup @@ -156,14 +156,14 @@ You can now determine if a user is authenticated on the client-side by checking ```html // example {#if !$session.user} -

I am not logged in

+

I am not logged in

{:else} -

Welcome {$session.user.email}

-

I am logged in!

+

Welcome {$session.user.email}

+

I am logged in!

{/if} ``` @@ -216,8 +216,8 @@ For [row level security](https://supabase.com/docs/learn/auth-deep-dive/auth-row ```html
Protected content for {user.email}
@@ -227,38 +227,41 @@ export let data; ```ts // src/routes/profile.ts -import { supabaseServerClient, withApiAuth } from "@supabase/auth-helpers-sveltekit"; -import type { RequestHandler } from "./__types/profile"; +import { + supabaseServerClient, + withApiAuth, +} from '@supabase/auth-helpers-sveltekit' +import type { RequestHandler } from './__types/profile' interface TestTable { - id: string; - created_at: string; + id: string + created_at: string } interface GetOutput { - user: User; - data: TestTable[]; + user: User + data: TestTable[] } export const GET: RequestHandler = async ({ locals }) => withApiAuth( { - redirectTo: "/", - user: locals.user + redirectTo: '/', + user: locals.user, }, async () => { const { data } = await supabaseServerClient(session.accessToken) - .from("test") - .select("*"); + .from('test') + .select('*') return { body: { user: locals.user, - data - } - }; + data, + }, + } } - ); + ) ``` ## Protecting API routes @@ -268,28 +271,33 @@ Wrap an API Route to check that the user has a valid session. If they're not log ```ts // src/routes/api/protected-route.ts -import { supabaseServerClient, withApiAuth } from "@supabase/auth-helpers-sveltekit"; -import type { RequestHandler } from "./__types/protected-route"; +import { + supabaseServerClient, + withApiAuth, +} from '@supabase/auth-helpers-sveltekit' +import type { RequestHandler } from './__types/protected-route' interface TestTable { - id: string; - created_at: string; + id: string + created_at: string } interface GetOutput { - data: TestTable[]; + data: TestTable[] } export const GET: RequestHandler = async ({ locals, request }) => withApiAuth({ user: locals.user }, async () => { // Run queries with RLS on the server - const { data } = await supabaseServerClient(request).from("test").select("*"); + const { data } = await supabaseServerClient(request) + .from('test') + .select('*') return { status: 200, - body: { data } - }; - }); + body: { data }, + } + }) ``` -If you visit `/api/protected-route` without a valid session cookie, you will get a 303 response. \ No newline at end of file +If you visit `/api/protected-route` without a valid session cookie, you will get a 303 response.