history: rokojori-auth built and deployed, Roject integration planned
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
714996fcae
commit
605afa3e66
|
|
@ -38,6 +38,7 @@ var NAV_DATA = {
|
|||
title: 'History',
|
||||
path: 'history/index.html',
|
||||
children: [
|
||||
{ title: 'Sunday, 13 July 2026', path: 'history/2026/07-July/13-Sunday/index.html' },
|
||||
{ title: 'Sunday, 12 July 2026', path: 'history/2026/07-July/12-Sunday/index.html' },
|
||||
{ title: 'Saturday, 11 July 2026', path: 'history/2026/07-July/11-Saturday/index.html' },
|
||||
{ title: 'Friday, 10 July 2026', path: 'history/2026/07-July/10-Friday/index.html' },
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sunday, 13 July 2026 — Roject</title>
|
||||
<link rel="stylesheet" href="../../../../_assets_/styles.css">
|
||||
<link rel="stylesheet" href="../../../../_assets_/nav.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
|
||||
<header>
|
||||
<p class="date">Sunday, 13 July 2026</p>
|
||||
<h1>rokojori-auth — built and deployed</h1>
|
||||
<p class="subtitle">
|
||||
Full centralized auth service created from scratch, deployed to
|
||||
<code>account.rokojori.com</code>, and documented.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<h2>What we built</h2>
|
||||
|
||||
<div class="card">
|
||||
<h3>rokojori-auth — new standalone service</h3>
|
||||
<p>
|
||||
A complete auth service at <code>c:\rokojori\projects\web-projects\rokojori-auth</code>,
|
||||
same stack as Roject (Node.js, Express, ts-node, JSON file storage). Built entirely
|
||||
from scratch this session. Deployed to <code>account.rokojori.com</code> via nginx +
|
||||
systemd + Let's Encrypt on Server A, port 3001.
|
||||
</p>
|
||||
<div class="tags">
|
||||
<span class="tag">account.rokojori.com</span>
|
||||
<span class="tag">nginx + systemd</span>
|
||||
<span class="tag">port 3001</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Auth endpoints</h3>
|
||||
<p>
|
||||
Register, login, logout, refresh (body), refresh-session (cookie + redirect),
|
||||
forgot-password, reset-password, GET /me, PATCH /me/settings, POST /me/password,
|
||||
DELETE /me. Access token is a 1-hour HS256 JWT containing userId, email, roles,
|
||||
products, settings. Refresh token is a 30-day UUID stored server-side.
|
||||
Both are set as <code>HttpOnly</code> cookies on <code>.rokojori.com</code>
|
||||
and also returned in the response body for non-browser clients.
|
||||
</p>
|
||||
<div class="tags">
|
||||
<span class="tag">jsonwebtoken</span>
|
||||
<span class="tag">bcryptjs</span>
|
||||
<span class="tag">cookie-parser</span>
|
||||
<span class="tag">HttpOnly cookie</span>
|
||||
<span class="tag">.rokojori.com domain</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Roles: user, admin, superadmin</h3>
|
||||
<p>
|
||||
Three built-in roles. <code>superadmin</code> is bootstrapped via
|
||||
<code>INITIAL_SUPERADMIN_EMAIL</code> in <code>.env</code> — fires once on
|
||||
first registration if no superadmin exists. Superadmin can grant/revoke admin
|
||||
on other users; cannot change their own roles. Admin and superadmin get an
|
||||
enhanced profile page with a full user list. Role management controls are
|
||||
superadmin-only.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Rate limiting</h3>
|
||||
<p>
|
||||
In-memory per-IP rate limiters on all sensitive endpoints. Login: 10 attempts /
|
||||
15 min, 3 s delay after attempt 5. Register: 5 / hour. Forgot-password: 20 / 20 min
|
||||
with escalating delay (5 s → 15 s → 30 s). <code>trust proxy</code> enabled so
|
||||
real client IPs are seen behind nginx.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>HTML pages</h3>
|
||||
<p>
|
||||
Five self-contained pages: login, register, profile, forgot-password, reset-password.
|
||||
Plain HTML with inline CSS and JS. Login and register accept a <code>?redirect=</code>
|
||||
query param. Reset-password fetches the email for the token via
|
||||
<code>GET /api/auth/reset-token-email</code> and populates a hidden email field
|
||||
so browsers offer to update the saved password. Profile page includes
|
||||
change-password (with current password verification) and a two-step delete account
|
||||
confirmation. Welcome email sent on registration (non-blocking).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Admin routes</h3>
|
||||
<p>
|
||||
<code>GET /api/admin/users</code> (admin + superadmin) lists all users without
|
||||
password hashes. <code>PATCH /api/admin/users/:id/roles</code> (superadmin only)
|
||||
sets roles on another user. Guards: cannot change own roles; <code>user</code>
|
||||
base role is always preserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Workspace documentation</h3>
|
||||
<p>
|
||||
Created <code>workspace/</code> in the rokojori-auth repo with the same asset
|
||||
system as the Roject workspace (styles, nav, breadcrumb). A single
|
||||
<code>workspace/index.html</code> covers features, technical implementation,
|
||||
data model, JWT payload, deployment, planned work, and a reference to the
|
||||
Roject workspace for guides and actions.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Key decisions</h2>
|
||||
|
||||
<div class="decision">
|
||||
<strong>Refresh token also set as HttpOnly cookie</strong>
|
||||
<p>
|
||||
Originally the refresh token was only returned in the response body. Added a
|
||||
refresh token cookie so browser clients can silently refresh via
|
||||
<code>GET /api/auth/refresh-session?redirect=...</code> without re-login.
|
||||
Non-browser clients continue to use the body token and
|
||||
<code>POST /api/auth/refresh</code>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="decision">
|
||||
<strong>Superadmin cannot change their own roles</strong>
|
||||
<p>
|
||||
The PATCH /api/admin/users/:id/roles endpoint blocks changes to the calling
|
||||
user's own record to prevent accidental self-demotion or lockout.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="decision">
|
||||
<strong>Welcome email is non-blocking</strong>
|
||||
<p>
|
||||
SMTP failures on the welcome email are caught and silently ignored so that a
|
||||
misconfigured mail server cannot break user registration.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="decision">
|
||||
<strong>Forgot-password always returns OK</strong>
|
||||
<p>
|
||||
The response is always <code>{ ok: true }</code> regardless of whether the email
|
||||
exists, preventing account enumeration via timing or response differences.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>What's next</h2>
|
||||
|
||||
<div class="card">
|
||||
<p>
|
||||
Integrate Roject with rokojori-auth: remove the local user system from Roject,
|
||||
add JWT verification middleware, redirect login/logout to
|
||||
<code>account.rokojori.com</code>, and update all data references from local
|
||||
user records to <code>userId</code> from the JWT payload.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
Roject — session history
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<script>var NAV_ROOT = '../../../../';</script>
|
||||
<script src="../../../../_assets_/nav-data.js"></script>
|
||||
<script src="../../../../_assets_/nav.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -19,6 +19,11 @@
|
|||
<section>
|
||||
<h2>2026 — July</h2>
|
||||
|
||||
<div class="card">
|
||||
<h3><a href="2026/07-July/13-Sunday/index.html">Sunday, 13 July 2026</a></h3>
|
||||
<p>rokojori-auth built and deployed — standalone auth service at account.rokojori.com with JWT tokens, refresh cookies, roles, rate limiting, admin panel, and workspace documentation.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3><a href="2026/07-July/12-Sunday/index.html">Sunday, 12 July 2026</a></h3>
|
||||
<p>Full directory restructure and first production deployment — source/, build/, source/pages/; Roject live at roject.rokojori.com via nginx + systemd. EmailService SMTP layer added.</p>
|
||||
|
|
|
|||
|
|
@ -231,17 +231,17 @@
|
|||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>In progress — Centralized auth: rokojori-auth</h3>
|
||||
<h3>Done — Centralized auth: rokojori-auth</h3>
|
||||
<p>
|
||||
The user system currently embedded in Roject is being extracted into a
|
||||
standalone auth service, <strong>rokojori-auth</strong>, deployed at
|
||||
<code>account.rokojori.com</code>. It will handle registration, login,
|
||||
JWT issuance, password reset, and user data (roles, products, settings)
|
||||
for all rokojori projects. Roject will become a JWT-validating client
|
||||
with no user storage of its own.
|
||||
The standalone auth service <strong>rokojori-auth</strong> is built and live at
|
||||
<code>account.rokojori.com</code>. It handles registration, login, JWT issuance,
|
||||
refresh token rotation, password reset, roles (user / admin / superadmin),
|
||||
products, global settings, rate limiting, and account deletion.
|
||||
Roject has not yet been integrated — that is the next step.
|
||||
</p>
|
||||
<p style="margin-top:0.75rem">
|
||||
See <a href="auth-restructure.html">auth-restructure</a> for the full plan.
|
||||
See <a href="auth-restructure.html">auth-restructure</a> for the full plan and
|
||||
the rokojori-auth workspace for implementation details.
|
||||
</p>
|
||||
<div class="tags">
|
||||
<span class="tag">rokojori-auth</span>
|
||||
|
|
@ -251,6 +251,35 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Next — Roject integration with rokojori-auth</h3>
|
||||
<p>
|
||||
Roject needs to be updated to become a JWT-validating client. The work involves
|
||||
removing the existing session-based user system and replacing it with JWT
|
||||
verification middleware that reads the shared <code>.rokojori.com</code> cookie.
|
||||
Login and register links will point to <code>account.rokojori.com</code>.
|
||||
Expired tokens are refreshed via
|
||||
<code>account.rokojori.com/api/auth/refresh-session?redirect=...</code>.
|
||||
All data models that currently reference a local user record will switch to
|
||||
referencing <code>userId</code> from the JWT payload.
|
||||
</p>
|
||||
<ul style="line-height:1.9;margin-top:0.75rem;font-size:0.9rem">
|
||||
<li>Remove <code>source/server/routes/auth.ts</code> and <code>middleware/auth.ts</code></li>
|
||||
<li>Remove user storage from <code>source/server/db.ts</code></li>
|
||||
<li>Remove <code>bcryptjs</code>, <code>express-session</code></li>
|
||||
<li>Remove <code>source/pages/login.html</code>, <code>register.html</code></li>
|
||||
<li>Remove <code>source/server/email/</code> (already lives in rokojori-auth)</li>
|
||||
<li>Add JWT verification middleware</li>
|
||||
<li>Point login/logout nav links at <code>account.rokojori.com</code></li>
|
||||
</ul>
|
||||
<div class="tags">
|
||||
<span class="tag">JWT middleware</span>
|
||||
<span class="tag">remove express-session</span>
|
||||
<span class="tag">remove bcryptjs</span>
|
||||
<span class="tag">account.rokojori.com login redirect</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Smaller open improvements</h3>
|
||||
<ul style="line-height:1.9">
|
||||
|
|
|
|||
Loading…
Reference in New Issue