node-refresh-token-rotation
An Express + Sequelize (Postgres) API that issues short-lived JWT access tokens and rotates refresh tokens on each use, storing them per user.
Problem
Keep JWT sessions short while allowing silent renewal, and be able to invalidate a leaked refresh token.
Built with
- Node.js
- Express
- Sequelize
- PostgreSQL
- JSON Web Tokens
- bcrypt
- winston
Architecture
Refresh-token rotation
Inferred- Refresh cookie Client presents the token
- Stored-token check Matches the user's token array
- Rotation Removes the used token
- New token pair Returns renewed credentials
Route layering
Inferredroutes/open holds the unauthenticated auth endpoints; routes/protected (users, employees) is mounted behind the jwtVerify middleware.
Refresh-token reuse handling
InferredBecause a refresh token is removed from the user's stored array when it is used, presenting an already-rotated token would not match any stored entry. The login path also rebuilds the array from the incoming cookie.
Evidence
Login signs a 1-minute access token and a 10-minute refresh token, both with APP_SECRET.
VerifiedRefresh tokens are stored as a JSONB array on the users table (refresh_token column, default empty array).
Verifiedmodels/user.js:1-25migrations/20221026114421-create-user.js:1-42
Protected routes sit behind a jwtVerify middleware that verifies the Authorization bearer token and loads the user by user_key, returning 401/403/404 as appropriate.
VerifiedPasswords are hashed with bcryptjs and compared with bcrypt.compare on login.
VerifiedDatabase schema is defined through sequelize-cli migrations for the users and employees tables.
Verifiedmigrations/20221026114421-create-user.jsmigrations/20221026120345-create-employee.js
Logging uses winston with an AsyncLocalStorage store so log lines can carry a per-request id.
VerifiedThe 404 handler in app.js calls an undefined createError, a leftover from an express-generator scaffold.
VerifiedContribution
Sole developer
Owner-confirmed sole work
Owner-confirmed: sole, original work; not based on a specific tutorial. Express + Sequelize (Postgres) API implementing JWT refresh-token rotation with reuse detection, bcrypt password hashing, and AsyncLocalStorage-based request-id logging.