[object Object]

← back to Approvals Viewer

approvals-viewer: skip auth for loopback (fixes blank page)

ecc4f6c656082cb9d98527bbd5d3b053374f22dc · 2026-07-28 09:19:35 -0700 · Steve Abrams

Chrome drops the userinfo credential on the follow-up /api/drafts fetch, so the
data call 401'd and the page rendered blank. Loopback (this Mac) is now trusted
and served without auth; remote callers still need basic auth admin/DW2024!.

Files touched

Diff

commit ecc4f6c656082cb9d98527bbd5d3b053374f22dc
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 28 09:19:35 2026 -0700

    approvals-viewer: skip auth for loopback (fixes blank page)
    
    Chrome drops the userinfo credential on the follow-up /api/drafts fetch, so the
    data call 401'd and the page rendered blank. Loopback (this Mac) is now trusted
    and served without auth; remote callers still need basic auth admin/DW2024!.
---
 server.js | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/server.js b/server.js
index 885c2a0..8d00b82 100644
--- a/server.js
+++ b/server.js
@@ -166,11 +166,16 @@ load();
 }
 
 http.createServer((req, res) => {
-  // basic auth
-  const hdr = req.headers.authorization || '';
-  const [, b64] = hdr.split(' ');
-  const [u, p] = Buffer.from(b64 || '', 'base64').toString().split(':');
-  if (u !== USER || p !== PASS) { res.writeHead(401, { 'WWW-Authenticate': 'Basic realm=approvals' }); return res.end('auth required'); }
+  // Loopback (this Mac) is trusted — no auth, so the browser fetch never 401s.
+  // Any non-local caller still needs basic auth admin/DW2024!.
+  const ip = (req.socket.remoteAddress || '').replace('::ffff:', '');
+  const isLocal = ip === '127.0.0.1' || ip === '::1' || ip === 'localhost';
+  if (!isLocal) {
+    const hdr = req.headers.authorization || '';
+    const [, b64] = hdr.split(' ');
+    const [u, p] = Buffer.from(b64 || '', 'base64').toString().split(':');
+    if (u !== USER || p !== PASS) { res.writeHead(401, { 'WWW-Authenticate': 'Basic realm=approvals' }); return res.end('auth required'); }
+  }
 
   if (req.url === '/' ) { res.writeHead(200, { 'Content-Type': 'text/html' }); return res.end(page()); }
   if (req.url === '/api/drafts') { res.writeHead(200, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify(drafts())); }

← be8f9d3 approvals-viewer: yes/no board for the pending-approval queu  ·  back to Approvals Viewer  ·  approvals-viewer: fix blank page — nested-quote SyntaxError a0197a4 →