1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-23 06:49:37 +02:00

feat: Update session cookie domain handling using publicsuffix2 and psl libraries

This commit is contained in:
Sean Morley 2025-01-26 20:06:47 -05:00
parent 6a5bfbda2d
commit d326d38329
5 changed files with 44 additions and 16 deletions

View file

@ -14,6 +14,7 @@ from dotenv import load_dotenv
from os import getenv from os import getenv
from pathlib import Path from pathlib import Path
from urllib.parse import urlparse from urllib.parse import urlparse
from publicsuffix2 import get_sld
# Load environment variables from .env file # Load environment variables from .env file
load_dotenv() load_dotenv()
@ -132,16 +133,26 @@ SESSION_COOKIE_SAMESITE = None
SESSION_COOKIE_SECURE = FRONTEND_URL.startswith('https') SESSION_COOKIE_SECURE = FRONTEND_URL.startswith('https')
# Parse the FRONTEND_URL
parsed_url = urlparse(FRONTEND_URL) parsed_url = urlparse(FRONTEND_URL)
hostname = parsed_url.hostname hostname = parsed_url.hostname
# Check if the hostname is an IP address
is_ip_address = hostname.replace('.', '').isdigit() is_ip_address = hostname.replace('.', '').isdigit()
if is_ip_address: if is_ip_address:
# Do not set a domain for IP addresses # Do not set a domain for IP addresses
SESSION_COOKIE_DOMAIN = None SESSION_COOKIE_DOMAIN = None
else: else:
# Calculate the cookie domain for valid domain names # Use publicsuffix2 to calculate the correct cookie domain
domain_parts = hostname.split('.') cookie_domain = get_sld(hostname)
SESSION_COOKIE_DOMAIN = '.' + '.'.join(domain_parts[-2:]) if len(domain_parts) > 1 else hostname if cookie_domain:
SESSION_COOKIE_DOMAIN = f".{cookie_domain}"
else:
# Fallback to the hostname if parsing fails
SESSION_COOKIE_DOMAIN = hostname
print("SESSION_COOKIE_DOMAIN:", SESSION_COOKIE_DOMAIN)
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)

View file

@ -20,4 +20,5 @@ django-ical==1.9.2
icalendar==6.1.0 icalendar==6.1.0
ijson==3.3.0 ijson==3.3.0
tqdm==4.67.1 tqdm==4.67.1
overpy==0.7 overpy==0.7
publicsuffix2==2.20191221

View file

@ -44,6 +44,7 @@
"emoji-picker-element": "^1.26.0", "emoji-picker-element": "^1.26.0",
"gsap": "^3.12.7", "gsap": "^3.12.7",
"marked": "^15.0.4", "marked": "^15.0.4",
"psl": "^1.15.0",
"qrcode": "^1.5.4", "qrcode": "^1.5.4",
"svelte-i18n": "^4.0.1", "svelte-i18n": "^4.0.1",
"svelte-maplibre": "^0.9.8", "svelte-maplibre": "^0.9.8",

View file

@ -23,6 +23,9 @@ importers:
marked: marked:
specifier: ^15.0.4 specifier: ^15.0.4
version: 15.0.4 version: 15.0.4
psl:
specifier: ^1.15.0
version: 1.15.0
qrcode: qrcode:
specifier: ^1.5.4 specifier: ^1.5.4
version: 1.5.4 version: 1.5.4
@ -1913,6 +1916,13 @@ packages:
protocol-buffers-schema@3.6.0: protocol-buffers-schema@3.6.0:
resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==}
psl@1.15.0:
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
qrcode@1.5.4: qrcode@1.5.4:
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
@ -4154,6 +4164,12 @@ snapshots:
protocol-buffers-schema@3.6.0: {} protocol-buffers-schema@3.6.0: {}
psl@1.15.0:
dependencies:
punycode: 2.3.1
punycode@2.3.1: {}
qrcode@1.5.4: qrcode@1.5.4:
dependencies: dependencies:
dijkstrajs: 1.0.3 dijkstrajs: 1.0.3

View file

@ -1,5 +1,6 @@
import { fail, redirect, type RequestEvent } from '@sveltejs/kit'; import { fail, redirect, type RequestEvent } from '@sveltejs/kit';
// @ts-ignore
import psl from 'psl';
import type { Actions, PageServerLoad, RouteParams } from './$types'; import type { Actions, PageServerLoad, RouteParams } from './$types';
import { getRandomBackground, getRandomQuote } from '$lib'; import { getRandomBackground, getRandomQuote } from '$lib';
import { fetchCSRFToken } from '$lib/index.server'; import { fetchCSRFToken } from '$lib/index.server';
@ -105,7 +106,7 @@ export const actions: Actions = {
} }
}; };
function handleSuccessfulLogin(event: RequestEvent, response: Response) { function handleSuccessfulLogin(event: RequestEvent<RouteParams, '/login'>, response: Response) {
const setCookieHeader = response.headers.get('Set-Cookie'); const setCookieHeader = response.headers.get('Set-Cookie');
if (setCookieHeader) { if (setCookieHeader) {
const sessionIdRegex = /sessionid=([^;]+).*?expires=([^;]+)/; const sessionIdRegex = /sessionid=([^;]+).*?expires=([^;]+)/;
@ -113,24 +114,22 @@ function handleSuccessfulLogin(event: RequestEvent, response: Response) {
if (match) { if (match) {
const [, sessionId, expiryString] = match; const [, sessionId, expiryString] = match;
// Get the proper cookie domain // Get the proper cookie domain using psl
const hostname = event.url.hostname; const hostname = event.url.hostname;
const domainParts = hostname.split('.'); let cookieDomain;
let cookieDomain: string | undefined = undefined;
// Check if hostname is an IP address // Check if hostname is an IP address
const isIPAddress = /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname); const isIPAddress = /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname);
if (!isIPAddress) { if (!isIPAddress) {
if (domainParts.length > 2) { const parsed = psl.parse(hostname);
// For subdomains like app.mydomain.com -> .mydomain.com
cookieDomain = '.' + domainParts.slice(-2).join('.'); if (parsed && parsed.domain) {
} else if (domainParts.length === 2) { // Use the parsed domain (e.g., mydomain.com)
// For root domains like mydomain.com -> .mydomain.com cookieDomain = `.${parsed.domain}`;
cookieDomain = '.' + hostname;
} }
} }
// Do not set a domain for IP addresses or single-part hostnames // Do not set a domain for IP addresses or invalid hostnames
console.log('Setting sessionid cookie with domain:', cookieDomain); console.log('Setting sessionid cookie with domain:', cookieDomain);