Skip to content

Middleware

Middleware files live in apps/backend/src/middleware/.


auth.middleware.js

Exports three request guard functions used to protect routes.


authCheck — Authenticated User Guard

Validates that the request has a valid JWT and that the session is still active (not revoked).

Used on: all /api/v1/user/*, /api/v1/unit/*, /api/v1/device/*, /api/v1/report/*, /api/v1/recipient/* routes.

Steps:

  1. Reads userAccessToken from req.cookies
  2. Verifies JWT signature and expiry using process.env.JWT_SECRET
  3. Looks up the token in the user_tokens collection (server-side revocation check)
  4. Looks up the user by decoded._id in the users collection
  5. Sets req.user = user and req.token = token
  6. Calls next()

Failure response: 401 { success: false, message: 'Please authenticate' }


adminAuthCheck — Admin-Only Guard

Performs the same full session validation as authCheck, then additionally checks that the user has type === 'admin'.

Used on: all /api/v1/admin/* routes.

Failure responses:

  • 401 { success: false, message: 'Please authenticate' } — invalid/missing token
  • 401 { success: false, message: 'Please authenticate' } — if user is not admin (same response, no leakage)

deviceAuthCheck — IoT Device Token Guard

Validates IoT hardware requests using a static shared secret in the Authorization header.

Used on: POST /api/v1/devices/sensor-data only.

Steps:

  1. Reads req.headers['authorization']
  2. Compares against the hardcoded token string
  3. Sets req.user = {}
  4. Calls next()

Failure response: 401 { success: false, message: 'Please authenticate' }

Security

The deviceAuthCheck uses a hardcoded static token. This value should be moved to an environment variable (DEVICE_AUTH_TOKEN) to allow rotation without code changes.


Middleware Usage in Routes

js
// user route — any logged-in user
router.get('/profile', authCheck, userController.getProfile)

// admin route — admin only
router.get('/', adminAuthCheck, adminUserController.listUsers)

// IoT device route — hardware token
router.post('/', deviceAuthCheck, deviceSensorDataController.saveSensorData)

Error Handling

There is a global error handler pattern defined in src/helpers/response.helper.js. Controllers are expected to catch errors themselves and use the response helpers:

js
const getProfile = async (req, res) => {
  try {
    const result = await userBusiness.getProfile(req.user._id)
    successResponse({ res, data: result })
  } catch (error) {
    console.error(error)
    internalServerError({ res })
  }
}

An Express catch-all error handler (app.use((err, req, res, next) => {...})) should be added after all route mounts to catch unhandled errors.

Intecog Logistech IoT Monitoring Platform