English | Русский
WebSec Users API is an educational security lab built with Node.js + Express, focused on secure user data management and access control in REST APIs.
The project addresses common API Security mistakes: exposing internal fields, accessing other users' objects, insufficient authorization, and mass assignment.
This is an educational security lab, not a production-ready identity service.
- Bearer token authentication for a demonstration API;
- role-based authorization for
adminanduser; - owner-based access control: users can work only with their own profiles;
- response filtering:
passwordHash, tokens, internal notes, and database IDs are not exposed; - an allowlist of updatable fields;
- protection against mass assignment and attempts to elevate roles through the request body;
- a consistent JSON error format;
- OpenAPI, Postman, automated tests, and GitHub Actions CI.
- Node.js
- Express
- JavaScript
- Node.js Test Runner
- OpenAPI
- Postman
- GitHub Actions
websec-users-api/
├── src/
│ ├── routes/
│ ├── middleware/
│ ├── services/
│ ├── data/
│ └── utils/
├── tests/
├── docs/
├── postman/
├── .github/workflows/ci.yml
├── .env.example
├── package.json
└── README.md
Use Node.js 22 (minimum 18). Check node --version.
Run the commands from the repository root. In PowerShell, copy the environment file
with Copy-Item .env.example .env.
git clone https://github.com/nikamurkaa/websec-users-api.git
cd websec-users-api
npm ci
cp .env.example .env
node --env-file=.env src/server.jsThe command above targets Node.js 22 and explicitly loads .env.
npm start uses only process environment variables and built-in defaults;
the script does not read .env on its own.
Default API address:
http://localhost:3000
Stop the server with Ctrl+C.
Example .env:
PORT=3000
ADMIN_TOKEN=admin-demo-token
USER_TOKEN=user-demo-tokenThese tokens are local demonstration values only.
| Method | Endpoint | Access |
|---|---|---|
GET |
/health |
Public |
GET |
/users/me |
Authenticated user |
GET |
/users |
Admin |
GET |
/users/:id |
Owner or admin |
PATCH |
/users/:id |
Owner or admin, with field restrictions |
Allowed update fields:
displayName;email;password.
Requests containing role, internal IDs, or other disallowed fields are rejected.
| Risk | Protection |
|---|---|
| Sensitive data exposure | public DTO / response filtering |
| Broken object authorization | owner check + admin override |
| Excessive privileges | RBAC |
| Mass assignment | PATCH field allowlist |
| Inconsistent errors | Central JSON error handler |
See docs/security-model.md for details.
The API returns only public user data. Responses exclude internal fields, including password hashes, tokens, internal notes, and database IDs.
A regular user cannot retrieve another user's profile. Attempts to access another user's object are rejected with 403 Forbidden.
An attempt to change the protected role field through a regular PATCH request is rejected by allowlist validation.
npm test
npm run checkManual scenarios: docs/manual-checks.md.
OpenAPI: docs/openapi.yaml.
Postman: postman/.
Completed as an educational lab on API authorization, object-level access control, and user data protection.


