Software
Reference
Authentication

Authentication

Start with --auth to require a 6-digit access code (printed at startup, changes every restart). Sessions persist 24 hours via HttpOnly cookies.

pieeg-server --auth

On startup you'll see:

╔══════════════════════════════════════╗
║        DASHBOARD ACCESS CODE         ║
║            Code: 847291              ║
╚══════════════════════════════════════╝

Flow

  1. User visits the dashboard → sees login form
  2. Enters the 6-digit code → POST /auth with { "code": "847291" }
  3. Server verifies (HMAC timing-safe compare) → sets HttpOnly session cookie
  4. Dashboard requests a WebSocket token → GET /auth/ws-token
  5. WebSocket connects with ?token=<ws-token>

Security Features

FeatureDetail
Rate limitingLockout after failed attempts
HMAC verificationTiming-safe comparison prevents timing attacks
HttpOnly cookiesSession cookies not accessible to JavaScript
Per-restart codesNew 6-digit code generated each server start
24-hour sessionsAutomatic expiry
⚠️

The access code is printed to the terminal at startup. Share it only with trusted users on your network.

Programmatic Authentication

const dashboardBase = "http://raspberrypi.local:1617";
const wsBase = "ws://raspberrypi.local:1616";
 
// 1. Authenticate
await fetch(`${dashboardBase}/auth`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  credentials: "include",
  body: JSON.stringify({ code: "847291" }),
});
 
// 2. Get WebSocket token
const { token } = await fetch(`${dashboardBase}/auth/ws-token`, {
  credentials: "include",
}).then((r) => r.json());
 
// 3. Connect
const ws = new WebSocket(`${wsBase}?token=${encodeURIComponent(token)}`);