JWT Authentication Middleware
Relevant source files - controllers/auth.controller.js - controllers/user.controller.js - middlewares/auth.middleware.js
The authorize middleware is the primary security gatekeeper for protected routes in the Subscription Tracker API. It implements stateless authentication using JSON Web Tokens (JWT) to verify the identity of requesting clients and populate user context for downstream handlers.
Implementation Overview
The middleware is defined in middlewares/auth.middleware.js5-35 It intercept incoming requests to validate the presence and integrity of a Bearer token. Upon successful validation, it retrieves the associated user from the MongoDB database—excluding sensitive fields—and attaches the user object to the req (request) object.
Logic Flow Diagram: Request Authorization
The following diagram illustrates the sequence of operations performed by the authorize middleware when a request hits a protected endpoint.
Middleware Sequence
sequenceDiagram
participant Client
participant authorize as "authorize (auth.middleware.js)"
participant JWT as "jsonwebtoken.verify"
participant DB as "User Model (MongoDB)"
participant Next as "Next Middleware/Controller"
Client->>authorize: Request with "Authorization: Bearer <token>"
authorize-->>Client: 401 Unauthorized
authorize->>JWT: verify(token, JWT_SECRET)
JWT-->>authorize: Throw Error
authorize-->>Client: 401 Unauthorized
JWT->>authorize: Return decoded payload { userId }
authorize->>DB: findById(userId).select("-password")
DB-->>authorize: null
authorize-->>Client: 401 Unauthorized
DB-->>authorize: userObject
authorize->>authorize: Set req.user = userObject
authorize->>Next: next()
Sources:middlewares/auth.middleware.js5-35controllers/auth.controller.js38-40controllers/auth.controller.js80-82
Key Technical Components
1. Token Extraction
The middleware looks for the token in the Authorization header. It specifically expects the Bearer schema middlewares/auth.middleware.js9-10 If the header is missing or does not start with "Bearer", the middleware immediately terminates the request with a 401 Unauthorized response middlewares/auth.middleware.js12-15
2. JWT Verification
The extraction process yields a string which is then verified using jwt.verify() against the JWT_SECRET loaded from environment variables middlewares/auth.middleware.js17
- Payload: The token is expected to contain a
userIdproperty, which was originally encoded during thesignUpcontrollers/auth.controller.js38-40 orsignIncontrollers/auth.controller.js80-82 processes. - Error Handling: Any error during verification (expired token, signature mismatch, malformed string) triggers the
catchblock, resulting in a401response middlewares/auth.middleware.js29-34
3. Identity Resolution & Security
Once the userId is decoded, the middleware queries the database to ensure the user still exists middlewares/auth.middleware.js19
- Password Exclusion: To maintain security, the query uses
.select("-password")to ensure the hashed password never enters the request context or subsequent logs middlewares/auth.middleware.js19 - Request Population: If found, the user document is assigned to
req.usermiddlewares/auth.middleware.js26 This allows controllers to access the authenticated user's data (e.g.,req.user._id) without performing redundant database lookups.
Code Entity Mapping
[Flowchart Diagram]
Sources:middlewares/auth.middleware.js1-35config/env.js5
Error Responses
The middleware enforces a strict "fail-fast" policy for authentication.
| Scenario | HTTP Status | Response Body |
|---|---|---|
| Missing Authorization header | 401 | {"message": "Unauthorized"} |
| Token does not start with "Bearer" | 401 | {"message": "Unauthorized"} |
| Expired or Invalid JWT | 401 | {"message": "Unauthorized", "error": "..."} |
| Valid JWT but User deleted from DB | 401 | {"message": "Unauthorized"} |
Sources:middlewares/auth.middleware.js12-15middlewares/auth.middleware.js21-24middlewares/auth.middleware.js29-34
Usage in Routing
The authorize middleware is imported and placed before controller logic in route definitions. For example, in the User API, it protects the "Get All Users" endpoint:
- File:
routes/user.routes.js(referenced by controllers/user.controller.js3) - Action: It ensures that only users with a valid token can fetch the list of all registered users.
Sources:middlewares/auth.middleware.js38controllers/user.controller.js3-13