📄 auth-handoff-daedalus.md 4,414 bytes Apr 24, 2026 📋 Raw

Auth Unification - Daedalus Handoff

Date: 2026-04-24
Status: Backend complete, frontend changes required
Test URL: http://100.71.120.12:8000 (or notes.hoffdesk.com when tunnel is fixed)


What Changed

Session-based authentication is now live. No more tokens in URLs or headers for browser traffic.

New Auth Flow

User visits /admin/blog/ 
    No session cookie?  Redirect to /auth/login?redirect=/admin/blog/
    User enters credentials  Session cookie set (30 days)
    Auto-redirect back to original page
    All subsequent requests include session cookie automatically

Your Action Items

1. Remove X-Admin-Token Header (HTMX Interceptor)

File: Your HTMX interceptor (wherever you set X-Admin-Token: hoffdesk-admin-2025)

Before:

// Remove this entire block
htmx.on('htmx:configRequest', (evt) => {
    evt.detail.headers['X-Admin-Token'] = 'hoffdesk-admin-2025';
});

After:

// HTMX automatically sends cookies on same-origin requests
// No code needed - cookies are automatic

2. Remove ?token= Query Parameters

Search for: ?token=hoffdesk-admin-2025 in your templates/JS

Before:

<a href="/admin/content/generate?token=hoffdesk-admin-2025">

After:

<a href="/admin/content/generate">
<!-- Cookie handles auth automatically -->

3. Handle 401 Responses

Add to your HTMX config:

htmx.on('htmx:responseError', (evt) => {
    if (evt.detail.xhr.status === 401) {
        window.location.href = '/auth/login?redirect=' + encodeURIComponent(window.location.pathname);
    }
});

4. Login Page Template (Optional)

The backend provides /auth/login with a styled form. If you want to customize it, the template is at:
- Backend: auth/router.pylogin_page() function (inline HTML)

To override: Create your own login template and have the backend redirect to it, or modify the inline HTML in auth/router.py.


Test Credentials

User Password Access
matt hoffdesk-matt-2026 admin, editor (full)
aundrea hoffdesk-aundrea-2026 family (family dashboard only)

Login endpoint: POST /auth/login
Logout: GET /auth/logout or POST /auth/logout


Magic Wand Fix

Problem: Content generation fetch doesn't include auth token.

Solution: Since cookies are automatic, just ensure fetch is same-origin:

// Before (broken - no auth)
fetch('/admin/content/generate', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(data)
});

// After (works - cookies automatic)
fetch('/admin/content/generate', {
    method: 'POST',
    credentials: 'same-origin',  // Include this
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(data)
});

If the Magic Wand uses vanilla JS fetch (not HTMX), add credentials: 'same-origin'.


API Routes (Unchanged)

Machine-to-machine routes still use Bearer tokens:

# Webhooks, Telegram callbacks
Authorization: Bearer <token>
# or
X-Hoffdesk-Secret: <token>

These routes were NOT changed:
- /webhook (Cloudflare Worker)
- /telegram/callback (Bot webhook)
- /family/events/removed (if called server-to-server)


Testing Checklist

# 1. Login
curl -X POST http://localhost:8000/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"matt","password":"hoffdesk-matt-2026"}' \
  -c cookies.txt

# 2. Access protected route
curl http://localhost:8000/admin/blog/ \
  -b cookies.txt

# 3. Check session
curl http://localhost:8000/auth/me -b cookies.txt
# → {"authenticated":true,"user_id":"matt",...}

# 4. Logout
curl http://localhost:8000/auth/logout -b cookies.txt -c cookies.txt

  • Name: hoffdesk_session
  • HttpOnly: Yes (JS can't read it, prevents XSS)
  • SameSite: Lax (CSRF protection)
  • Max-Age: 30 days
  • Path: /

Questions?

Ask Socrates (backend) or check shared/session_auth.py for the auth implementation.

Key files:
- main.py — Middleware wiring
- auth/router.py — Login/logout endpoints
- shared/session_auth.py — Session + Bearer validation
- shared/project-docs/auth-unification.md — Full spec


Ready for frontend implementation. 🎨