Merge pull request 'feat: Add wildcard support for trusted domains' (#20) from fix/trusted-origins-wildcards into master
Reviewed-on: https://code.cannabrands.app/Creationshop/dispensary-scraper/pulls/20
This commit is contained in:
@@ -32,6 +32,7 @@ const TRUSTED_ORIGINS = [
|
|||||||
// Pattern-based trusted origins (wildcards)
|
// Pattern-based trusted origins (wildcards)
|
||||||
const TRUSTED_ORIGIN_PATTERNS = [
|
const TRUSTED_ORIGIN_PATTERNS = [
|
||||||
/^https:\/\/.*\.cannabrands\.app$/, // *.cannabrands.app
|
/^https:\/\/.*\.cannabrands\.app$/, // *.cannabrands.app
|
||||||
|
/^https:\/\/.*\.cannaiq\.co$/, // *.cannaiq.co
|
||||||
];
|
];
|
||||||
|
|
||||||
// Trusted IPs for internal pod-to-pod communication
|
// Trusted IPs for internal pod-to-pod communication
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { Request, Response, NextFunction } from 'express';
|
|||||||
* These are our own frontends that should have unrestricted access.
|
* These are our own frontends that should have unrestricted access.
|
||||||
*/
|
*/
|
||||||
const TRUSTED_DOMAINS = [
|
const TRUSTED_DOMAINS = [
|
||||||
'cannaiq.co',
|
'*.cannaiq.co',
|
||||||
'www.cannaiq.co',
|
'*.cannabrands.app',
|
||||||
'findagram.co',
|
'findagram.co',
|
||||||
'www.findagram.co',
|
'www.findagram.co',
|
||||||
'findadispo.com',
|
'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
|
* 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)
|
// Check Origin header first (preferred for CORS requests)
|
||||||
if (origin) {
|
if (origin) {
|
||||||
const domain = extractDomain(origin);
|
const domain = extractDomain(origin);
|
||||||
if (domain && TRUSTED_DOMAINS.includes(domain)) {
|
if (domain && isTrustedDomain(domain)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +68,7 @@ function isRequestFromTrustedDomain(req: Request): boolean {
|
|||||||
// Fallback to Referer header
|
// Fallback to Referer header
|
||||||
if (referer) {
|
if (referer) {
|
||||||
const domain = extractDomain(referer);
|
const domain = extractDomain(referer);
|
||||||
if (domain && TRUSTED_DOMAINS.includes(domain)) {
|
if (domain && isTrustedDomain(domain)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,12 @@ const CONSUMER_TRUSTED_ORIGINS = [
|
|||||||
'http://localhost:3002',
|
'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)
|
// Trusted IPs for local development (bypass API key auth)
|
||||||
const TRUSTED_IPS = ['127.0.0.1', '::1', '::ffff:127.0.0.1'];
|
const TRUSTED_IPS = ['127.0.0.1', '::1', '::ffff:127.0.0.1'];
|
||||||
|
|
||||||
@@ -150,8 +156,17 @@ function isConsumerTrustedRequest(req: Request): boolean {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const origin = req.headers.origin;
|
const origin = req.headers.origin;
|
||||||
if (origin && CONSUMER_TRUSTED_ORIGINS.includes(origin)) {
|
if (origin) {
|
||||||
return true;
|
// 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;
|
const referer = req.headers.referer;
|
||||||
if (referer) {
|
if (referer) {
|
||||||
@@ -160,6 +175,18 @@ function isConsumerTrustedRequest(req: Request): boolean {
|
|||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user