Skip to content

Dashboard sign-in

The Hub uses different credentials for different jobs.

Credential Use it for Do not use it for
Dashboard password Everyday browser sign-in REST/MCP bearer auth
Server access token (ADHD_HUB_AUTH_TOKEN) REST/MCP, first setup, password recovery Routine browser sign-in after you create a password
CLI session (ahcli_…) Client REST/MCP after adhd-hub login Server configuration or password recovery

This is a single-owner, self-hosted sign-in flow.

First-time setup

  1. Set ADHD_HUB_AUTH_TOKEN to a private random value on the server and restart the hub. Generate one with python -c "import secrets; print(secrets.token_urlsafe(32))". Keep it in your environment or untracked .env.
  2. Open /ui/ and sign in with that access token.
  3. Choose Create password, or Settings → Account → Create or change password. Verify with your access token, then enter and confirm a password of at least 12 characters. It must differ from your access token.
  4. Future visits default to password sign-in. The page supports password managers and a show/hide control, and Need help signing in? under the card repeats these steps.

No password is configured automatically. Local development with the default token can still run on loopback, but password setup requires a private server token first.

Change or recover a password

In Settings, choose Create or change password and verify with either your current password or your recovery access token. Saving a password revokes every previous browser session and gives the current browser a new session. Assistant connections retain their access token.

If you forget your password, choose Use access token instead on the sign-in page, sign in with ADHD_HUB_AUTH_TOKEN, and reset the password in Settings. A damaged password file can also be replaced using this flow. If the access token is lost, set a new one in the server environment and restart the hub, then use it to recover access; update your MCP clients too.

Storage and sessions

  • Passwords are salted and hashed with scrypt (N=32768, r=8, p=3, 32-byte output), atomically stored in data/dashboard-password.hash with mode 0600. The password itself is never saved.
  • Browser sessions expire after 12 hours. Cookies are HttpOnly and SameSite=Strict; HTTPS enables Secure. Credentials are never written to localStorage.
  • Sessions are stored in SQLite (data/browser_sessions.sqlite3) and survive process restart and multiple workers. Login throttles stay in process memory, so a restart clears those counters.
  • Password setup, password sign-in, and token sign-in share a limit of five attempts per client IP per minute. A successful attempt clears that client's counter. Configure trusted proxy headers correctly so a reverse proxy supplies the real client IP and HTTPS scheme.
  • Cookie-authenticated writes require X-Hub-Request: 1; an Origin, when present, must match the server origin. Use HTTPS for remote access.
  • Backup export deliberately excludes the password hash, browser sessions, and CLI connect grants (data/connect.sqlite3). Restoring project data does not overwrite credentials. On a new machine, set its server token and create a password again, or separately migrate the private hash file while retaining its permissions. Re-run adhd-hub login on each client.

Auth endpoints

All auth responses disable caching. Invalid auth requests return field locations and generic validation messages without echoing submitted credentials. Browser writes require X-Hub-Request: 1.

Endpoint Request
GET /api/auth/status Reports whether a password is configured and whether development mode is active; returns no secrets.
POST /api/auth/login Exactly one of password or token; issues a session cookie.
PUT /api/auth/password current_method (password or token), current_secret, and a new password; verifies the credential again even if already signed in.
POST /api/auth/logout Revokes the current browser session.

Dashboard passwords cannot be used as bearer credentials for REST or MCP. Those clients continue to use ADHD_HUB_AUTH_TOKEN, or a CLI session issued by adhd-hub login (see Connect). The CLI session is stored on the client disk, not in your shell environment, and is not the server access token.

CLI connect handshake

POST /api/connect/start (unauthenticated, rate-limited) creates a 10-minute, single-use grant. The operator approves it while signed into /ui (POST /api/connect/approve). The CLI then calls POST /api/connect/token once (poll with device_code, or the one-time code delivered to http://127.0.0.1:<port>/callback). Replay, expiry, and a wrong PKCE verifier are rejected. Issued ahcli_ tokens are hashed in data/connect.sqlite3 and last 90 days or until revoked.