diff --git a/src/inc/lib.mjs b/src/inc/lib.mjs index 45ded46..cd0e66e 100644 --- a/src/inc/lib.mjs +++ b/src/inc/lib.mjs @@ -460,4 +460,14 @@ export default new class { console.error(`[ERROR REF ${errId}] ${context}:`, err); return `Internal Error. Reference: ${errId}`; } + + isOnionRequest(req) { + if (!req || !req.headers) return false; + const rawHost = req.headers['x-forwarded-host'] || req.headers['host'] || ''; + if (!rawHost) return false; + const firstHost = rawHost.split(',')[0].trim(); + const hostNoPort = firstHost.split(':')[0].trim().toLowerCase(); + return hostNoPort.endsWith('.onion'); + } }; + diff --git a/src/inc/routes/register.mjs b/src/inc/routes/register.mjs index 640bdb8..e686a5d 100644 --- a/src/inc/routes/register.mjs +++ b/src/inc/routes/register.mjs @@ -89,7 +89,7 @@ export default (router, tpl) => { } // reCAPTCHA verification (bypassed for .onion requests as Google reCAPTCHA cannot validate .onion domains) - const isOnion = req.headers['host']?.endsWith('.onion'); + const isOnion = lib.isOnionRequest(req); if (!isOnion && cfg.recaptcha?.enabled && cfg.recaptcha?.secret_key) { const rcToken = req.post['g-recaptcha-response']; if (!rcToken) return renderError("Please complete the reCAPTCHA."); diff --git a/src/index.mjs b/src/index.mjs index 9467fb6..555ba41 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -79,11 +79,13 @@ const nginx502Fallback = ` `; // Login + Register modal injected before -// This string is built at startup so it can reference cfg.recaptcha values. +// Dynamic function so reCAPTCHA can be bypassed for .onion requests const _rcEnabled = !!(cfg.recaptcha && cfg.recaptcha.enabled && cfg.recaptcha.site_key); const _rcSiteKey = (cfg.recaptcha && cfg.recaptcha.site_key) || ''; -const gateLoginInjection = ` +function getGateLoginInjection(req) { + const rcEnabled = _rcEnabled && !lib.isOnionRequest(req); + return `