From 113268614b0b8217bad5bfaf1cbd8e8b20c10a81 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:27:52 +0100 Subject: [PATCH] feat(#14): Update code to match documentation --- src/hooks.server.ts | 37 ++++++++++++++++-------------- src/routes/+layout.server.ts | 5 ++-- src/routes/+layout.svelte | 4 ++-- src/routes/+layout.ts | 31 +++++++++++++------------ src/routes/+page.svelte | 2 -- src/routes/auth/error/+page.svelte | 1 + 6 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 src/routes/auth/error/+page.svelte diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 6d6e55e..f49fd46 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -5,45 +5,48 @@ import type { Handle } from '@sveltejs/kit'; export const handle: Handle = async ({ event, resolve }) => { event.locals.supabase = createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, { cookies: { - get: (key) => event.cookies.get(key), + getAll: () => event.cookies.getAll(), /** - * Note: You have to add the `path` variable to the - * set and remove method due to sveltekit's cookie API - * requiring this to be set, setting the path to an empty string - * will replicate previous/standard behaviour (https://kit.svelte.dev/docs/types#public-types-cookies) + * SvelteKit's cookies API requires `path` to be explicitly set in + * the cookie options. Setting `path` to `/` replicates previous/ + * standard behavior. */ - set: (key, value, options) => { - event.cookies.set(key, value, { ...options, path: '/' }); - }, - remove: (key, options) => { - event.cookies.delete(key, { ...options, path: '/' }); + setAll: (cookiesToSet) => { + cookiesToSet.forEach(({ name, value, options }) => { + event.cookies.set(name, value, { ...options, path: '/' }); + }); } } }); /** - * Unlike `supabase.auth.getSession`, which is unsafe on the server because it - * doesn't validate the JWT, this function validates the JWT by first calling - * `getUser` and aborts early if the JWT signature is invalid. + * Unlike `supabase.auth.getSession()`, which returns the session _without_ + * validating the JWT, this function also calls `getUser()` to validate the + * JWT before returning the session. */ event.locals.safeGetSession = async () => { + const { + data: { session } + } = await event.locals.supabase.auth.getSession(); + if (!session) { + return { session: null, user: null }; + } + const { data: { user }, error } = await event.locals.supabase.auth.getUser(); if (error) { + // JWT validation has failed return { session: null, user: null }; } - const { - data: { session } - } = await event.locals.supabase.auth.getSession(); return { session, user }; }; return resolve(event, { filterSerializedResponseHeaders(name) { - return name === 'content-range'; + return name === 'content-range' || name === 'x-supabase-api-version'; } }); }; diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index 1d33583..847fb80 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -1,10 +1,11 @@ import type { LayoutServerLoad } from './$types'; -export const load: LayoutServerLoad = async ({ locals: { safeGetSession } }) => { +export const load: LayoutServerLoad = async ({ locals: { safeGetSession }, cookies }) => { const { session, user } = await safeGetSession(); return { session, - user + user, + cookies: cookies.getAll() }; }; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 71184bc..3b9e286 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -32,8 +32,8 @@ let cookiesAccepted = false; onMount(() => { - const { data } = supabase.auth.onAuthStateChange((event, _session) => { - if (_session?.expires_at !== session?.expires_at) { + const { data } = supabase.auth.onAuthStateChange((event, newSession) => { + if (newSession?.expires_at !== session?.expires_at) { // tells SvelteKit that the root +layout.ts load function should be executed whenever the session updates to keep the page store in sync. invalidate('supabase:auth'); } diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 80875ca..37bbb09 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,25 +1,26 @@ +import { createBrowserClient, createServerClient, isBrowser } from '@supabase/ssr'; import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from '$env/static/public'; import type { LayoutLoad } from './$types'; -import { createBrowserClient, isBrowser, parse } from '@supabase/ssr'; export const load: LayoutLoad = async ({ fetch, data, depends }) => { depends('supabase:auth'); - const supabase = createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, { - global: { - fetch - }, - cookies: { - get(key) { - if (!isBrowser()) { - return JSON.stringify(data.session); + const supabase = isBrowser() + ? createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, { + global: { + fetch } - - const cookie = parse(document.cookie); - return cookie[key]; - } - } - }); + }) + : createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, { + global: { + fetch + }, + cookies: { + getAll() { + return data.cookies; + } + } + }); /** * It's fine to use `getSession` here, because on the client, `getSession` is diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index bcfc5a1..136c686 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,6 +1,4 @@