From 05c20ec0a2557e70fd17b3834edf5feb53745d79 Mon Sep 17 00:00:00 2001 From: Bruno Bernardino Date: Sun, 2 Mar 2025 07:24:28 +0000 Subject: [PATCH] Optionally skip domain in cookie (#43) If you're using a reverse proxy like Cloudflare Tunnels, you can now set `CONFIG_SKIP_COOKIE_DOMAIN_SECURITY="true"` to avoid login issues. Also makes some UX tweaks to Expenses, and fixes a style issue for Chrome in Windows (#44). Fixes #43 Fixes #44 --- .env.sample | 1 + components/expenses/BudgetModal.tsx | 18 ++++++++++-------- components/expenses/ExpenseModal.tsx | 15 ++++++++------- lib/auth.ts | 14 +++++++++++++- lib/config.ts | 6 ++++++ static/styles.css | 5 +++++ 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/.env.sample b/.env.sample index 99f6e91..1d26394 100644 --- a/.env.sample +++ b/.env.sample @@ -19,3 +19,4 @@ CONFIG_FILES_ROOT_PATH="data-files" CONFIG_ENABLE_EMAILS="false" # if true, email verification will be required for signups (using Brevo) CONFIG_ENABLE_FOREVER_SIGNUP="true" # if true, all signups become active for 100 years # CONFIG_ALLOWED_COOKIE_DOMAINS="example.com,example.net" # can be set to allow more than the BASE_URL's domain for session cookies +# CONFIG_SKIP_COOKIE_DOMAIN_SECURITY="true" # if true, the cookie domain will not be strictly set and checked against. This skipping slightly reduces security, but is usually necessary for reverse proxies like Cloudflare Tunnel. diff --git a/components/expenses/BudgetModal.tsx b/components/expenses/BudgetModal.tsx index 8a0fada..8fc3e1f 100644 --- a/components/expenses/BudgetModal.tsx +++ b/components/expenses/BudgetModal.tsx @@ -85,13 +85,15 @@ export default function BudgetModal( { newBudgetValue.value = Number(event.currentTarget.value); }} + min='0' + inputmode='decimal' placeholder='100' /> @@ -100,7 +102,7 @@ export default function BudgetModal( {budget ? ( - + diff --git a/components/expenses/ExpenseModal.tsx b/components/expenses/ExpenseModal.tsx index 7b9761b..04c32a6 100644 --- a/components/expenses/ExpenseModal.tsx +++ b/components/expenses/ExpenseModal.tsx @@ -119,6 +119,7 @@ export default function ExpenseModal( onInput={(event) => { newExpenseCost.value = Number(event.currentTarget.value); }} + inputmode='decimal' placeholder='10.99' /> @@ -222,7 +223,7 @@ export default function ExpenseModal( {expense ? ( + - diff --git a/lib/auth.ts b/lib/auth.ts index 6d9c055..d58120c 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -6,7 +6,7 @@ import 'std/dotenv/load.ts'; import { baseUrl, generateHash, isRunningLocally } from './utils/misc.ts'; import { User, UserSession } from './types.ts'; import { createUserSession, deleteUserSession, getUserByEmail, validateUserAndSession } from './data/user.ts'; -import { isCookieDomainAllowed } from './config.ts'; +import { isCookieDomainAllowed, isCookieDomainSecurityDisabled } from './config.ts'; const JWT_SECRET = Deno.env.get('JWT_SECRET') || ''; export const PASSWORD_SALT = Deno.env.get('PASSWORD_SALT') || ''; @@ -173,6 +173,10 @@ export async function logoutUser(request: Request) { domain: resolveCookieDomain(request), }; + if (isCookieDomainSecurityDisabled()) { + delete cookie.domain; + } + const response = new Response('Logged Out', { status: 303, headers: { 'Location': '/', 'Content-Type': 'text/html; charset=utf-8' }, @@ -222,6 +226,10 @@ export async function createSessionCookie( domain: resolveCookieDomain(request), }; + if (isCookieDomainSecurityDisabled()) { + delete cookie.domain; + } + setCookie(response.headers, cookie); return response; @@ -246,6 +254,10 @@ export async function updateSessionCookie( domain: resolveCookieDomain(request), }; + if (isCookieDomainSecurityDisabled()) { + delete cookie.domain; + } + setCookie(response.headers, cookie); return response; diff --git a/lib/config.ts b/lib/config.ts index 91b0392..2b9ad16 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -30,6 +30,12 @@ export function isCookieDomainAllowed(domain: string) { return allowedDomains.includes(domain); } +export function isCookieDomainSecurityDisabled() { + const isCookieDomainSecurityDisabled = Deno.env.get('CONFIG_SKIP_COOKIE_DOMAIN_SECURITY') === 'true'; + + return isCookieDomainSecurityDisabled; +} + export function isEmailEnabled() { const areEmailsAllowed = Deno.env.get('CONFIG_ENABLE_EMAILS') === 'true'; diff --git a/static/styles.css b/static/styles.css index ccaf59f..4cf13e4 100644 --- a/static/styles.css +++ b/static/styles.css @@ -2,6 +2,11 @@ @tailwind components; @tailwind utilities; +html { + /* This is needed to ensure that the system color scheme is dark and matches the dark theme of the app */ + color-scheme: dark; +} + h1 { @apply text-4xl font-bold; }