DC-029: skip authLimiter for already-authenticated requests
The DC-027 rate limiter on /api/v1/auth/* shipped with skip: () => isTest,
which counted every request — including those from a logged-in TOTP session.
Caddy's forward_auth fires /auth/gate/* on every page-load asset (HTML, JS,
CSS, XHR), so a normal browser session exhausted the 20-req/15-min budget
within ~3 page loads and started getting 429 'Too many auth requests' even
with a valid session cookie.
Fix: extend skip to also return true when req.auth.type is 'session',
'jwt', or 'apikey' (set by jwtApiKeyAuthMiddleware, which runs upstream
of the limiter). The unauthenticated path is still rate-limited — DC-027's
credential-scraping defense is preserved.
Also closes the uncommitted working-tree changes for:
- DC-026: routes/auth/sso-gate.js — pre-auth check in buildLoginPage,
redirected error fallbacks to status.sami?auth=required&return=...
- DC-022: dashcaddy-api/VERSION bumped to fef7e07
- status/index.html + status/js/tailscale-devices.js — Tailscale device card
4 new regression tests pin the fix:
- skips when req.auth.type === 'session'
- skips when req.auth.type === 'jwt'
- skips when req.auth.type === 'apikey'
- still counts UNAUTHENTICATED requests (defense preserved)
Live verified: 50/50 authenticated /auth/gate/plex calls passed (was
20/30 before fix). plex.sami/dashcaddy-login returns 200 with no redirect
loop. Plex auto-login token round-trips end-to-end.
This commit is contained in:
@@ -276,6 +276,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" data-app="tailscale" data-status="off" id="tailscale-card"
|
||||
title="Devices on your Tailscale network. Online = connected right now. Offline = known to the network but not currently connected.">
|
||||
<span id="tailscale-dot" class="dot bad at-bl"></span>
|
||||
<div class="row">
|
||||
<div class="logo-wrap">
|
||||
<svg viewBox="0 0 24 24" class="service-icon" aria-hidden="true">
|
||||
<path d="M12 2L4 7v6c0 5 3.5 8.5 8 9 4.5-.5 8-4 8-9V7l-8-5z" fill="none" stroke="#7D8FE3" stroke-width="2" stroke-linejoin="round"/>
|
||||
<circle cx="12" cy="10" r="2.5" fill="#7D8FE3"/>
|
||||
<path d="M12 13v4M9 19h6" stroke="#7D8FE3" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="name">Tailscale</span>
|
||||
<span class="spacer"></span>
|
||||
<span id="tailscale-pill" class="badge off">—</span>
|
||||
</div>
|
||||
<div class="response-row">
|
||||
<span id="tailscale-summary" class="response-time" style="font-size: 0.7rem;">Loading…</span>
|
||||
</div>
|
||||
<div class="btn-row">
|
||||
<button id="tailscale-refresh-btn" title="Refresh device list">↻</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" data-app="ca" data-status="off">
|
||||
<span id="dot-ca-grid" class="dot bad at-bl"></span>
|
||||
<div class="row">
|
||||
@@ -302,6 +325,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tailscale Device Panel (collapsible, populated by tailscale-devices.js) -->
|
||||
<div id="tailscale-panel" style="display: none; margin-bottom: 16px; padding: 16px; background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius);">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<span style="font-size: 1.1rem; font-weight: 600;">Devices on Tailscale</span>
|
||||
<span id="tailscale-panel-count" style="color: var(--muted); font-size: 0.85rem;"></span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<span id="tailscale-tailnet" style="color: var(--muted); font-size: 0.8rem; align-self: center;"></span>
|
||||
<button id="tailscale-panel-close" class="btn-sm" title="Close panel" style="padding: 4px 10px;">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tailscale-device-list" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Service Filter Bar -->
|
||||
<div id="service-filter-bar" style="display: flex; gap: 12px; align-items: center; margin-bottom: 16px; padding: 12px 16px; background: var(--card-base); border: 1px solid var(--border); border-radius: var(--radius); flex-wrap: wrap;">
|
||||
<input type="text" id="service-filter-search" placeholder="🔍 Filter services..." style="flex: 1; min-width: 180px; padding: 8px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; color: var(--fg); font-size: 0.9rem;" />
|
||||
@@ -906,6 +944,9 @@
|
||||
<script src="/js/xterm.min.js" defer></script>
|
||||
<script src="/js/xterm-fit.min.js" defer></script>
|
||||
|
||||
<!-- Tailscale device list panel (self-contained, polls /api/v1/tailscale/devices) -->
|
||||
<script src="/js/tailscale-devices.js" defer></script>
|
||||
|
||||
<!-- Bundled JS (built with: npm run build) -->
|
||||
<script src="/dist/core.js" defer></script>
|
||||
<script src="/dist/features.js" defer></script>
|
||||
|
||||
Reference in New Issue
Block a user