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
metadata
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
- Open the Space → Sign up → create an account → click Open the Planner.
- The planner (
/app) loads habits, tasks and focus sessions from the server API — nothing in IndexedDB. - Try opening
/appwhile logged out: the server redirects you to the login. - 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.sidcookie ishttpOnly,sameSite=lax, automaticallySecurebehind the Space's HTTPS; secret generated withcrypto.randomBytesand persisted. - Session regeneration on login (anti fixation) and login rate limiting.
/appoutsideexpress.static: the file lives inprivate/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=laxcovers the basic case); no HTTPS of its own (the Space proxy handles it).