token header on every request that touches private data — such as the cart or order endpoints. Requests that omit a valid token are rejected before they reach the route handler.
How authentication works
1
User registers or logs in
Calling
POST /api/user/register or POST /api/user/login with valid credentials returns a signed JWT. The token payload contains the user’s MongoDB _id encoded under the id key.2
Client stores the token
The React frontend persists the token in
localStorage under the key "token". On page load, StoreContext reads it back and re-attaches it to every subsequent API call automatically.frontend/src/context/StoreContext.jsx
3
Protected endpoints verify the token
Every protected route passes the request through
authMiddleware before the controller runs. The middleware reads req.headers.token, verifies it against JWT_SECRET, and injects userId into req.body so controllers can use it directly.backend/middleware/auth.js
Register a new user
This endpoint is public — no token is required.
POST /api/user/register
Creates a new user account, validates the supplied data, hashes the password with bcrypt, persists the record to MongoDB, and returns a signed JWT on success.
Request body
string
required
The user’s display name. Stored as-is in the
user collection.string
required
A valid email address. Validated with the
validator library — malformed addresses are rejected before the record is created. Must be unique across all accounts.string
required
Plain-text password. Must be at least 8 characters. Hashed with bcrypt at salt-rounds 10 before being stored — the raw password is never persisted.
Responses
boolean
true when the account was created and a token was issued.string
Signed JWT — present only on a successful response.
Example
Login
This endpoint is public — no token is required.
POST /api/user/login
Looks up the user by email, compares the supplied password against the stored bcrypt hash, and returns a signed JWT on success.
Request body
string
required
The email address used when the account was created.
string
required
The account password in plain text. It is compared against the stored hash using
bcrypt.compare — never logged or stored.Responses
boolean
true when credentials matched and a token was issued.string
Signed JWT — present only on a successful response.
Example
Using the token
Pass the JWT returned from register or login as atoken HTTP header on every protected request. The middleware decodes it and automatically injects the userId into the request — you do not need to include userId in the request body yourself.
frontend/src/context/StoreContext.jsx
Tokens are created with
jwt.sign({id}, process.env.JWT_SECRET) and no expiresIn option is set, so tokens are valid indefinitely. They only become invalid if the JWT_SECRET environment variable changes on the server.Protected endpoints
The following endpoints require a validtoken header. Requests without one — or with a token signed by a different secret — are rejected by authMiddleware before reaching the controller.