From 22dad6d0fcae6e0a0e4f5aece6734a2adc59632e Mon Sep 17 00:00:00 2001 From: Kelly Date: Wed, 10 Dec 2025 15:21:13 -0700 Subject: [PATCH 1/2] feat: Add wildcard trusted origins for cannaiq.co and cannabrands.app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add *.cannaiq.co and *.cannabrands.app patterns to both: - auth/middleware.ts (admin routes) - public-api.ts (consumer /api/v1/* routes) This allows any subdomain of these domains to access the API without requiring an API key. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- backend/src/auth/middleware.ts | 1 + backend/src/routes/public-api.ts | 31 +++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/backend/src/auth/middleware.ts b/backend/src/auth/middleware.ts index 15e82d53..1a7aec9c 100755 --- a/backend/src/auth/middleware.ts +++ b/backend/src/auth/middleware.ts @@ -32,6 +32,7 @@ const TRUSTED_ORIGINS = [ // Pattern-based trusted origins (wildcards) const TRUSTED_ORIGIN_PATTERNS = [ /^https:\/\/.*\.cannabrands\.app$/, // *.cannabrands.app + /^https:\/\/.*\.cannaiq\.co$/, // *.cannaiq.co ]; // Trusted IPs for internal pod-to-pod communication diff --git a/backend/src/routes/public-api.ts b/backend/src/routes/public-api.ts index 7179fa8b..61265ca1 100644 --- a/backend/src/routes/public-api.ts +++ b/backend/src/routes/public-api.ts @@ -130,6 +130,12 @@ const CONSUMER_TRUSTED_ORIGINS = [ 'http://localhost:3002', ]; +// Wildcard trusted origin patterns (*.domain.com) +const CONSUMER_TRUSTED_PATTERNS = [ + /^https:\/\/([a-z0-9-]+\.)?cannaiq\.co$/, + /^https:\/\/([a-z0-9-]+\.)?cannabrands\.app$/, +]; + // Trusted IPs for local development (bypass API key auth) const TRUSTED_IPS = ['127.0.0.1', '::1', '::ffff:127.0.0.1']; @@ -150,8 +156,17 @@ function isConsumerTrustedRequest(req: Request): boolean { return true; } const origin = req.headers.origin; - if (origin && CONSUMER_TRUSTED_ORIGINS.includes(origin)) { - return true; + if (origin) { + // Check exact matches + if (CONSUMER_TRUSTED_ORIGINS.includes(origin)) { + return true; + } + // Check wildcard patterns + for (const pattern of CONSUMER_TRUSTED_PATTERNS) { + if (pattern.test(origin)) { + return true; + } + } } const referer = req.headers.referer; if (referer) { @@ -160,6 +175,18 @@ function isConsumerTrustedRequest(req: Request): boolean { return true; } } + // Check wildcard patterns against referer origin + try { + const refererUrl = new URL(referer); + const refererOrigin = refererUrl.origin; + for (const pattern of CONSUMER_TRUSTED_PATTERNS) { + if (pattern.test(refererOrigin)) { + return true; + } + } + } catch { + // Invalid referer URL, ignore + } } return false; } From f25bebf6ee967873b91466d106196416194c5993 Mon Sep 17 00:00:00 2001 From: Kelly Date: Wed, 10 Dec 2025 15:29:23 -0700 Subject: [PATCH 2/2] feat: Add wildcard support for trusted domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add *.cannaiq.co and *.cannabrands.app to trusted domains list. Updated isTrustedDomain() to recognize *.domain.com as wildcard that matches the base domain and any subdomain. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- backend/src/middleware/trustedDomains.ts | 26 ++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/backend/src/middleware/trustedDomains.ts b/backend/src/middleware/trustedDomains.ts index f904dbaf..9a55857a 100644 --- a/backend/src/middleware/trustedDomains.ts +++ b/backend/src/middleware/trustedDomains.ts @@ -5,8 +5,8 @@ import { Request, Response, NextFunction } from 'express'; * These are our own frontends that should have unrestricted access. */ const TRUSTED_DOMAINS = [ - 'cannaiq.co', - 'www.cannaiq.co', + '*.cannaiq.co', + '*.cannabrands.app', 'findagram.co', 'www.findagram.co', 'findadispo.com', @@ -32,6 +32,24 @@ function extractDomain(header: string): string | null { } } +/** + * Checks if a domain matches any trusted domain (supports *.domain.com wildcards) + */ +function isTrustedDomain(domain: string): boolean { + for (const trusted of TRUSTED_DOMAINS) { + if (trusted.startsWith('*.')) { + // Wildcard: *.example.com matches example.com and any subdomain + const baseDomain = trusted.slice(2); + if (domain === baseDomain || domain.endsWith('.' + baseDomain)) { + return true; + } + } else if (domain === trusted) { + return true; + } + } + return false; +} + /** * Checks if the request comes from a trusted domain */ @@ -42,7 +60,7 @@ function isRequestFromTrustedDomain(req: Request): boolean { // Check Origin header first (preferred for CORS requests) if (origin) { const domain = extractDomain(origin); - if (domain && TRUSTED_DOMAINS.includes(domain)) { + if (domain && isTrustedDomain(domain)) { return true; } } @@ -50,7 +68,7 @@ function isRequestFromTrustedDomain(req: Request): boolean { // Fallback to Referer header if (referer) { const domain = extractDomain(referer); - if (domain && TRUSTED_DOMAINS.includes(domain)) { + if (domain && isTrustedDomain(domain)) { return true; } }