Spaces:
Sleeping
Sleeping
|
Download README.md from Offlin33er/planner-auth: direct link, hf CLI and curl.
- Browser
- Download file 3.33 kB
-
https://huggingface.co/spaces/Offlin33er/planner-auth/resolve/main/README.md
- Command line
-
hf download hf://spaces/Offlin33er/planner-auth/README.md
-
curl -L -o README.md https://huggingface.co/spaces/Offlin33er/planner-auth/resolve/main/README.md
3.33 kB
| title: Planner Auth — Real Authentication | |
| emoji: 🔐 | |
| colorFrom: indigo | |
| colorTo: green | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: false | |
| license: mit | |
| # Planner Auth 🔐 | |
| A **real (server-side) authentication server** **+ protected planner**: passwords hashed with bcrypt, sessions managed by the server with an `httpOnly` cookie, each user's data stored and filtered **on the server**, and an `/app` page that only opens with a valid session. | |
| ## How to use it | |
| 1. Open the Space → **Sign up** → create an account → click **Open the Planner**. | |
| 2. The planner (`/app`) loads habits, tasks and focus sessions **from the server API** — nothing in IndexedDB. | |
| 3. Try opening `/app` while logged out: the server redirects you to the login. | |
| 4. Reload the page: you're still logged in (the session lives on the server). | |
| ## Endpoints | |
| ### Authentication | |
| | Route | What it does | | |
| |---|---| | |
| | `POST /api/register` | validates, hashes with bcrypt (10 rounds), creates the user, starts a session | | |
| | `POST /api/login` | bcrypt compare, **regenerates the session** (anti fixation), rate limit of 5 tries / 15 min | | |
| | `POST /api/logout` | destroys the session on the server | | |
| | `GET /api/me` | protected — returns the session's user, or 401 | | |
| | `POST /api/forgot-password` | random token, stored only as a SHA-256 hash, 15 min validity | | |
| | `POST /api/reset-password` | validates the token (single use) and replaces the password hash | | |
| ### Per-user data — all require a session and filter by `owner` | |
| | Route | What it does | | |
| |---|---| | |
| | `GET/POST /api/habits`, `PUT/DELETE /api/habits/:id` | the logged-in user's habits (emoji, color, daily/weekly with a goal) | | |
| | `GET /api/checkins`, `POST /api/checkins/toggle` | daily completions (`{habitId, date}`), validates habit ownership | | |
| | `GET/POST /api/tasks`, `PUT/DELETE /api/tasks/:id`, `POST /api/tasks/reorder` | tasks with priority and due date, reordering by id list | | |
| | `GET/POST /api/sessions` | focus (pomodoro) sessions | | |
| | `GET /app` | the planner page — **redirects to `/` without a session** | | |
| ## Security details | |
| - **bcrypt** with 10 rounds — the password is never stored as plain text. | |
| - **Server-side session**: the `planner.sid` cookie is `httpOnly`, `sameSite=lax`, automatically `Secure` behind the Space's HTTPS; secret generated with `crypto.randomBytes` and persisted. | |
| - **Session regeneration on login** (anti fixation) and login rate limiting. | |
| - **`/app` outside `express.static`**: the file lives in `private/` and is only served by the route that requires a session — there is no way to download it directly. | |
| - **Per-user isolation on the server**: every data route filters by `owner = current session`; a user cannot read or change another user's data, even by forging ids. | |
| - **Reset token** stored as a SHA-256 hash, single use, expiring; the "forgot password" response is identical whether the e-mail exists or not. | |
| ## Honest limitations | |
| - Storage is `data/db.json` (swap for SQLite/Postgres in production). | |
| - Sessions are in memory (`MemoryStore`) — they don't survive a Space restart; use Redis in production. | |
| - No e-mail in a Space: the reset token comes back in the API response (demo). In production it would go by e-mail. | |
| - No explicit CSRF token (`sameSite=lax` covers the basic case); no HTTPS of its own (the Space proxy handles it). |