Skip to content

feat: OBS-backed login system - #1

Open
AgustinChiarenza wants to merge 1 commit into
mainfrom
feat/obs-auth-login
Open

feat: OBS-backed login system#1
AgustinChiarenza wants to merge 1 commit into
mainfrom
feat/obs-auth-login

Conversation

@AgustinChiarenza

Copy link
Copy Markdown
Owner

Adds a login system that reads credentials from an OBS object (Auth/users.json) in the same bucket as the ops data — no secrets in source.

Backend

  • app/auth.py: loads the user table from OBS (60s TTL cache), HMAC-SHA256 token sign/verify (stdlib only). Accepts password or password_sha256.
  • app/routers/auth.py: POST /api/auth/login, GET /api/auth/me, POST /api/auth/logout.
  • app/main.py: middleware gating all /api/* except /api/health, /api/auth/login, /api/auth/logout.
  • app/config.py: AUTH_ENABLED, AUTH_USERS_PATH, AUTH_SECRET, AUTH_TOKEN_TTL_SECONDS.

Frontend

  • auth/AuthContext + useAuth: session state, validates cached token via /auth/me on boot.
  • pages/LoginPage: split-panel login matching the brand palette.
  • api/client: axios interceptor attaches Bearer and redirects to /login on 401.
  • layout/Header: user avatar, role, and sign-out menu.
  • App.tsx / main.tsx: routes gated behind AuthProvider.

Ops

  • scripts/seed_auth_users.py: idempotent seeder — reads passwords from env vars (ADMIN_PASSWORD, VIEWER_PASSWORD), no hardcoded secrets.
  • .env.example: documents the new auth vars.

Verified

  • /api/health public ✓
  • login ok → token+user ✓ · wrong password → 401 ✓
  • protected route without token → 401 ✓ · with token → 200 ✓
  • /api/auth/me with token → user ✓

Test plan

  • Seed OBS: docker exec -e ADMIN_PASSWORD=... cloud-ops-backend python /app/scripts/seed_auth_users.py
  • Open :8082 → redirects to /login
  • Login with seeded creds → dashboard loads
  • Sign out from header → back to /login
  • Set AUTH_ENABLED=false → dashboard open as before

🤖 Generated with Claude Code

Credentials are read from an OBS object (Auth/users.json) in the same bucket
as the ops data, so no secrets live in source. The backend issues HMAC-SHA256
signed tokens (stdlib only) and middleware gates every /api/* route except
health and the auth endpoints. The frontend gates routes behind an AuthProvider,
attaches the bearer token via an axios interceptor, auto-redirects to /login on
401, and exposes sign-out from the header.

Backend:
- app/auth.py: OBS credential loader (TTL cached) + token sign/verify
- app/routers/auth.py: /login, /me, /logout
- app/main.py: auth middleware + router registration
- app/config.py: AUTH_ENABLED, AUTH_USERS_PATH, AUTH_SECRET, AUTH_TOKEN_TTL_SECONDS

Frontend:
- auth/AuthContext + useAuth: session state, /me validation on boot
- pages/LoginPage: designed split-panel login
- api/client: bearer + 401 interceptors
- layout/Header: user menu + sign out

Ops:
- scripts/seed_auth_users.py: idempotent seeder (reads passwords from env, no
  hardcoded secrets)
- .env.example: document auth vars
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant