mirror of
https://github.com/jcreek/LivingDexTracker.git
synced 2026-09-14 17:42:17 +00:00
fix(auth): stop stale session cookies signing users out on refresh
@supabase/ssr 0.1.0 never removed the old unchunked session cookie once a refreshed session grew past one cookie, and always read that stale copy first. Every load then retried an already-used refresh token, which the hosted auth server rejects, signing the user out. Upgrade @supabase/ssr to 0.12 (and supabase-js to match) and move to the getAll/setAll cookie API, which clears stale chunks when writing.
This commit is contained in:
Generated
+67
-91
@@ -8,8 +8,8 @@
|
||||
"name": "livingdextracker",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@supabase/ssr": "^0.1.0",
|
||||
"@supabase/supabase-js": "^2.42.0",
|
||||
"@supabase/ssr": "^0.12.7",
|
||||
"@supabase/supabase-js": "^2.116.0",
|
||||
"nanoid": "^5.0.4",
|
||||
"sharp": "^0.33.4"
|
||||
},
|
||||
@@ -3728,103 +3728,120 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@supabase/auth-js": {
|
||||
"version": "2.89.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.89.0.tgz",
|
||||
"integrity": "sha512-wiWZdz8WMad8LQdJMWYDZ2SJtZP5MwMqzQq3ehtW2ngiI3UTgbKiFrvMUUS3KADiVlk4LiGfODB2mrYx7w2f8w==",
|
||||
"version": "2.116.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.116.0.tgz",
|
||||
"integrity": "sha512-Cmosty12gyKGK9N3bQb+lMmuAFev5nmUzaR1AsmZHqKOAGzqX1VQzmp49CNPwOx/pw0H9Qqk4rs9yhwTlKpfDg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/functions-js": {
|
||||
"version": "2.89.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.89.0.tgz",
|
||||
"integrity": "sha512-XEueaC5gMe5NufNYfBh9kPwJlP5M2f+Ogr8rvhmRDAZNHgY6mI35RCkYDijd92pMcNM7g8pUUJov93UGUnqfyw==",
|
||||
"version": "2.116.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.116.0.tgz",
|
||||
"integrity": "sha512-E+VOc2QDcni/fySqkBFiZhnoB3SGydEdZgFI6/dEAGAHx6yEhB46TN9qb2wXs+E+RSzOBV0R6dasiSlw4xlZAA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/phoenix": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/phoenix/-/phoenix-0.4.5.tgz",
|
||||
"integrity": "sha512-aAn9H9ovVyeApKy11OWOrrOGq8DV68yWeH4ud2lN9fzn4aO8Zb5GLL9m1pUg9nLqIcT+ZDfAcsZe0E/nqdv2lw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@supabase/postgrest-js": {
|
||||
"version": "2.89.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.89.0.tgz",
|
||||
"integrity": "sha512-/b0fKrxV9i7RNOEXMno/I1862RsYhuUo+Q6m6z3ar1f4ulTMXnDfv0y4YYxK2POcgrOXQOgKYQx1eArybyNvtg==",
|
||||
"version": "2.116.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.116.0.tgz",
|
||||
"integrity": "sha512-kGpVZTDHxFTJS3tu+rU0iTAZ+4U0bcLVjxwCk8f3gRhjw3qdCZjTBlgYvc4kGH2XccmAzbkKwXL/mrNHMGSc+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/realtime-js": {
|
||||
"version": "2.89.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.89.0.tgz",
|
||||
"integrity": "sha512-aMOvfDb2a52u6PX6jrrjvACHXGV3zsOlWRzZsTIOAJa0hOVvRp01AwC1+nLTGUzxzezejrYeCX+KnnM1xHdl+w==",
|
||||
"version": "2.116.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.116.0.tgz",
|
||||
"integrity": "sha512-MHAnlXxi2s6yiJsZsQMfs2B3RFxeVfQWxerqYhIMqcCQV/FuY3LIeouPEkXw/ah7wUWMLYwempF9MOCUScyddg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/phoenix": "^1.6.6",
|
||||
"@types/ws": "^8.18.1",
|
||||
"tslib": "2.8.1",
|
||||
"ws": "^8.18.2"
|
||||
"@supabase/phoenix": "0.4.5",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/ssr": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.1.0.tgz",
|
||||
"integrity": "sha512-bIVrkqjAK5G3KjkIMKYKtAOlCgRRplEWjrlyRyXSOYtgDieiOhk2ZyNAPsEOa1By9OZVxuX5eAW1fitdnuxayw==",
|
||||
"version": "0.12.7",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.12.7.tgz",
|
||||
"integrity": "sha512-wiBtEie1KkRJi9RrZWY3R2imRhX1JY7qMyUCH2z9AUk15gQebNEplM+urbCKamdxaTJLXUU6LlpkJsaxhojCEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cookie": "^0.5.0",
|
||||
"ramda": "^0.29.0"
|
||||
"cookie": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@supabase/supabase-js": "^2.33.1"
|
||||
"@supabase/supabase-js": "^2.114.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/ssr/node_modules/cookie": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
|
||||
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/storage-js": {
|
||||
"version": "2.89.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.89.0.tgz",
|
||||
"integrity": "sha512-6zKcXofk/M/4Eato7iqpRh+B+vnxeiTumCIP+Tz26xEqIiywzD9JxHq+udRrDuv6hXE+pmetvJd8n5wcf4MFRQ==",
|
||||
"version": "2.116.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.116.0.tgz",
|
||||
"integrity": "sha512-6/3hR6vccBP6oGM5B6RfbwZcTCKmQOodd/ZWQdsw8yJsU5zO/a//oBL6yLnmgxcjnHSrelW8rsO7hL5DPybyUQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iceberg-js": "^0.8.1",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/supabase-js": {
|
||||
"version": "2.89.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.89.0.tgz",
|
||||
"integrity": "sha512-KlaRwSfFA0fD73PYVMHj5/iXFtQGCcX7PSx0FdQwYEEw9b2wqM7GxadY+5YwcmuEhalmjFB/YvqaoNVF+sWUlg==",
|
||||
"version": "2.116.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.116.0.tgz",
|
||||
"integrity": "sha512-YyWmKXt2NspV9iO8FPnlswUFJIRnrLd3oTCb+3ZyYRuKZtBH0xCUDgnUqoyA0fGUxpM/UhfwDjYf/dht/9bp7g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/auth-js": "2.89.0",
|
||||
"@supabase/functions-js": "2.89.0",
|
||||
"@supabase/postgrest-js": "2.89.0",
|
||||
"@supabase/realtime-js": "2.89.0",
|
||||
"@supabase/storage-js": "2.89.0"
|
||||
"@supabase/auth-js": "2.116.0",
|
||||
"@supabase/functions-js": "2.116.0",
|
||||
"@supabase/postgrest-js": "2.116.0",
|
||||
"@supabase/realtime-js": "2.116.0",
|
||||
"@supabase/storage-js": "2.116.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=22.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@opentelemetry/api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
||||
@@ -4016,16 +4033,12 @@
|
||||
"version": "20.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz",
|
||||
"integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/phoenix": {
|
||||
"version": "1.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz",
|
||||
"integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/pug": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz",
|
||||
@@ -4062,15 +4075,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz",
|
||||
@@ -9020,15 +9024,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/ramda": {
|
||||
"version": "0.29.1",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz",
|
||||
"integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ramda"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -10908,7 +10903,9 @@
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||
"version": "2.0.0",
|
||||
@@ -12268,27 +12265,6 @@
|
||||
"node": "^20.17.0 || >=22.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "15.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||
|
||||
+2
-2
@@ -78,8 +78,8 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@supabase/ssr": "^0.1.0",
|
||||
"@supabase/supabase-js": "^2.42.0",
|
||||
"@supabase/ssr": "^0.12.7",
|
||||
"@supabase/supabase-js": "^2.116.0",
|
||||
"nanoid": "^5.0.4",
|
||||
"sharp": "^0.33.4"
|
||||
},
|
||||
|
||||
+8
-11
@@ -1,23 +1,20 @@
|
||||
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
|
||||
import { createServerClient } from '@supabase/ssr';
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
import type { CookieSerializeOptions } from 'cookie';
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
event.locals.supabase = createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
|
||||
cookies: {
|
||||
get: (key: string) => 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)
|
||||
* Note: You have to add the `path` variable to the set method due to sveltekit's cookie
|
||||
* API requiring this to be set, setting the path to '/' will replicate previous/standard
|
||||
* behaviour (https://kit.svelte.dev/docs/types#public-types-cookies)
|
||||
*/
|
||||
set: (key: string, value: string, options: CookieSerializeOptions) => {
|
||||
event.cookies.set(key, value, { ...options, path: '/' });
|
||||
},
|
||||
remove: (key: string, options: CookieSerializeOptions) => {
|
||||
event.cookies.delete(key, { ...options, path: '/' });
|
||||
setAll: (cookiesToSet) => {
|
||||
cookiesToSet.forEach(({ name, value, options }) => {
|
||||
event.cookies.set(name, value, { ...options, path: '/' });
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
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,
|
||||
// The universal layout load rebuilds a server-side client from these during SSR.
|
||||
cookies: cookies.getAll()
|
||||
};
|
||||
};
|
||||
|
||||
+16
-23
@@ -1,7 +1,6 @@
|
||||
import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from '$env/static/public';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import { createBrowserClient, isBrowser, parse, serialize } from '@supabase/ssr';
|
||||
import type { CookieSerializeOptions } from 'cookie';
|
||||
import { createBrowserClient, createServerClient, isBrowser } from '@supabase/ssr';
|
||||
|
||||
export const load: LayoutLoad = async ({ fetch, data, depends }) => {
|
||||
depends('supabase:auth');
|
||||
@@ -31,29 +30,23 @@ export const load: LayoutLoad = async ({ fetch, data, depends }) => {
|
||||
return response;
|
||||
};
|
||||
|
||||
const supabase = createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
|
||||
global: {
|
||||
fetch: authFetch
|
||||
},
|
||||
cookies: {
|
||||
get(key: string) {
|
||||
if (!isBrowser()) {
|
||||
return JSON.stringify(data.session);
|
||||
// The browser client manages document.cookie itself, including removing stale session chunks.
|
||||
const supabase = isBrowser()
|
||||
? createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
|
||||
global: {
|
||||
fetch: authFetch
|
||||
}
|
||||
|
||||
const cookie = parse(document.cookie);
|
||||
return cookie[key];
|
||||
},
|
||||
set(key: string, value: string, options: CookieSerializeOptions) {
|
||||
if (isBrowser()) document.cookie = serialize(key, value, { ...options, path: '/' });
|
||||
},
|
||||
remove(key: string, options: CookieSerializeOptions) {
|
||||
if (isBrowser()) {
|
||||
document.cookie = serialize(key, '', { ...options, path: '/', maxAge: 0 });
|
||||
})
|
||||
: 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
|
||||
|
||||
Reference in New Issue
Block a user