[object Object]

← back to AbramsOS

Harden auth cookies for public HTTPS surface + record claims subdomain deploy

d08f146dfc0edd88db81f07e31f7879010a51427 · 2026-07-31 15:20:29 -0700 · Steve Abrams

- trust proxy=1 (behind Kamatera nginx) so req.secure reflects X-Forwarded-Proto.
- Session + CSRF cookies now secure:req.secure — Secure over HTTPS subdomain,
  plain over direct tailnet http (no lockout). Closes cookie-in-transit leak on
  the now-public claims.abramsos.agentabrams.com PII surface.
- Records the deployed nginx vhost (45.61.58.125:80/443 -> 100.82.17.107:9774).
Found by /yoloforever cycle-1 contrarian gate; verified Secure-on-https / plain-on-http.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit d08f146dfc0edd88db81f07e31f7879010a51427
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Jul 31 15:20:29 2026 -0700

    Harden auth cookies for public HTTPS surface + record claims subdomain deploy
    
    - trust proxy=1 (behind Kamatera nginx) so req.secure reflects X-Forwarded-Proto.
    - Session + CSRF cookies now secure:req.secure — Secure over HTTPS subdomain,
      plain over direct tailnet http (no lockout). Closes cookie-in-transit leak on
      the now-public claims.abramsos.agentabrams.com PII surface.
    - Records the deployed nginx vhost (45.61.58.125:80/443 -> 100.82.17.107:9774).
    Found by /yoloforever cycle-1 contrarian gate; verified Secure-on-https / plain-on-http.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 deploy/claims.abramsos.agentabrams.com.nginx.conf | 2 +-
 middleware/csrf.js                                | 2 +-
 routes/auth-app.js                                | 4 ++--
 server.js                                         | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/deploy/claims.abramsos.agentabrams.com.nginx.conf b/deploy/claims.abramsos.agentabrams.com.nginx.conf
index bf5c78e..0af8c8d 100644
--- a/deploy/claims.abramsos.agentabrams.com.nginx.conf
+++ b/deploy/claims.abramsos.agentabrams.com.nginx.conf
@@ -2,7 +2,7 @@
 # Cloned from animals.agentabrams.com (plain proxy; AbramsOS has its own requireAuth).
 # certbot --nginx injects its own acme-challenge handler + adds the 443 block.
 server {
-  listen 80;
+  listen 45.61.58.125:80;
   server_name claims.abramsos.agentabrams.com;
   location / {
     proxy_pass http://100.82.17.107:9774;   # this Mac (tailnet), AbramsOS :9774
diff --git a/middleware/csrf.js b/middleware/csrf.js
index acad605..f798081 100644
--- a/middleware/csrf.js
+++ b/middleware/csrf.js
@@ -19,7 +19,7 @@ function ensureToken(req, res, next) {
       httpOnly: false,            // body must read it
       sameSite: 'lax',
       maxAge: TTL_MS,
-      secure: false,              // dev http
+      secure: req.secure,         // Secure over HTTPS (subdomain); plain over direct http — no lockout
     });
   }
   res.locals.csrfToken = token;
diff --git a/routes/auth-app.js b/routes/auth-app.js
index 4cd881f..cbfa943 100644
--- a/routes/auth-app.js
+++ b/routes/auth-app.js
@@ -45,7 +45,7 @@ router.post('/signup', async (req, res) => {
 
     // Sign them into a temporary session so they can complete TOTP enrollment
     const { sid } = await auth.createSession(DEV_USER_ID, meta);
-    res.cookie(auth.SESSION_COOKIE, sid, { httpOnly: true, sameSite: 'lax', maxAge: auth.SESSION_TTL_MS });
+    res.cookie(auth.SESSION_COOKIE, sid, { httpOnly: true, sameSite: 'lax', maxAge: auth.SESSION_TTL_MS, secure: req.secure });
     res.redirect('/enroll-totp');
   } catch (err) {
     console.error('[signup]', err);
@@ -117,7 +117,7 @@ router.post('/signin', async (req, res) => {
 
     // Begin a session marked as NOT step-upped yet
     const { sid } = await auth.createSession(userId, meta);
-    res.cookie(auth.SESSION_COOKIE, sid, { httpOnly: true, sameSite: 'lax', maxAge: auth.SESSION_TTL_MS });
+    res.cookie(auth.SESSION_COOKIE, sid, { httpOnly: true, sameSite: 'lax', maxAge: auth.SESSION_TTL_MS, secure: req.secure });
     return res.render('signin', { stage: 'totp', error: null, next });
   }
 
diff --git a/server.js b/server.js
index 1b0e16c..ba33c86 100644
--- a/server.js
+++ b/server.js
@@ -40,7 +40,7 @@ const PORT = parseInt(process.env.PORT || '9931', 10);
 
 app.set('view engine', 'ejs');
 app.set('views', path.join(__dirname, 'views'));
-app.set('trust proxy', 'loopback');
+app.set('trust proxy', 1);   // behind Kamatera nginx (sets X-Forwarded-Proto) — makes req.secure accurate over HTTPS
 
 app.use(helmet({ contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }));
 app.use(morgan('tiny'));

← 69b613c auto-save: 2026-07-31T14:58:42 (1 files) — deploy/claims.abr  ·  back to AbramsOS  ·  Stop unauth info-disclosure on public surface (/healthz + er 8c7f239 →