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 --authOn startup you’ll see:
╔══════════════════════════════════════╗
║ DASHBOARD ACCESS CODE ║
║ Code: 847291 ║
╚══════════════════════════════════════╝Flow
- User visits the dashboard → sees login form
- Enters the 6-digit code →
POST /authwith{ "code": "847291" } - Server verifies (HMAC timing-safe compare) → sets HttpOnly session cookie
- Dashboard requests a WebSocket token →
GET /auth/ws-token - WebSocket connects with
?token=<ws-token>
Security Features
| Feature | Detail |
|---|---|
| Rate limiting | Lockout after failed attempts |
| HMAC verification | Timing-safe comparison prevents timing attacks |
| HttpOnly cookies | Session cookies not accessible to JavaScript |
| Per-restart codes | New 6-digit code generated each server start |
| 24-hour sessions | Automatic 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)}`);