diff --git a/package-lock.json b/package-lock.json index 192f46a8..91239834 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "html-prettify": "~1.0.7", "idb-keyval": "~6.2.1", "intl-locale-textinfo-polyfill": "~2.1.1", + "js-cookie": "~3.0.5", "just-debounce-it": "~3.2.0", "lz-string": "~1.5.0", "masto": "~6.8.0", @@ -7472,6 +7473,14 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-sha256": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz", diff --git a/package.json b/package.json index 0afab5dd..52c96793 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "html-prettify": "~1.0.7", "idb-keyval": "~6.2.1", "intl-locale-textinfo-polyfill": "~2.1.1", + "js-cookie": "~3.0.5", "just-debounce-it": "~3.2.0", "lz-string": "~1.5.0", "masto": "~6.8.0", diff --git a/src/app.jsx b/src/app.jsx index 606b9d0c..bf18e23a 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -321,9 +321,9 @@ function App() { window.location.pathname || '/', ); - const clientID = store.session.get('clientID'); - const clientSecret = store.session.get('clientSecret'); - const vapidKey = store.session.get('vapidKey'); + const clientID = store.sessionCookie.get('clientID'); + const clientSecret = store.sessionCookie.get('clientSecret'); + const vapidKey = store.sessionCookie.get('vapidKey'); (async () => { setUIState('loading'); diff --git a/src/pages/login.jsx b/src/pages/login.jsx index 8956385c..21d52bd4 100644 --- a/src/pages/login.jsx +++ b/src/pages/login.jsx @@ -64,9 +64,9 @@ function Login() { }); if (client_id && client_secret) { - store.session.set('clientID', client_id); - store.session.set('clientSecret', client_secret); - store.session.set('vapidKey', vapid_key); + store.sessionCookie.set('clientID', client_id); + store.sessionCookie.set('clientSecret', client_secret); + store.sessionCookie.set('vapidKey', vapid_key); location.href = await getAuthorizationURL({ instanceURL, diff --git a/src/utils/store.js b/src/utils/store.js index fb587b11..19309885 100644 --- a/src/utils/store.js +++ b/src/utils/store.js @@ -1,5 +1,9 @@ +import Cookies from 'js-cookie'; + import { getCurrentAccountNS } from './store-utils'; +const cookies = Cookies.withAttributes({ sameSite: 'strict', secure: true }); + const local = { get: (key) => { try { @@ -86,6 +90,38 @@ const session = { }, }; +// Session secure cookie +const cookie = { + get: (key) => cookies.get(key), + set: (key, value) => cookies.set(key, value), + del: (key) => cookies.remove(key), +}; + +// Cookie with sessionStorage fallback +const sessionCookie = { + get: (key) => { + if (navigator.cookieEnabled) { + return cookie.get(key); + } else { + return session.get(key); + } + }, + set: (key, value) => { + if (navigator.cookieEnabled) { + return cookie.set(key, value); + } else { + return session.set(key, value); + } + }, + del: (key) => { + if (navigator.cookieEnabled) { + return cookie.del(key); + } else { + return session.del(key); + } + }, +}; + // Store with account namespace (id@domain.tld) <- uses id, not username const account = { get: (key) => { @@ -118,4 +154,4 @@ const account = { }, }; -export default { local, session, account }; +export default { local, session, sessionCookie, cookie, account };