Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/fredy-rizo/despacho-backend/llms.txt

Use this file to discover all available pages before exploring further.

Despacho Backend secures its lawyer-facing endpoints with JSON Web Tokens (JWT). When a lawyer account is created, the password is hashed and stored safely in MongoDB. On every subsequent login, the server verifies the credentials and issues a signed JWT that the client must include in every protected request. Tokens are valid for 365 days, so lawyers stay authenticated across long work sessions without needing to re-login frequently.

How authentication works

Registration

Sending a POST request to /api/lawyer/user/create with email and password in the request body triggers the following sequence:
  1. The server checks that both fields are present; missing fields return 403.
  2. The email is checked for uniqueness — duplicate emails return 203.
  3. The password is hashed with bcrypt at cost factor 10 via encryptPassword().
  4. A new LawyerUser document is saved to MongoDB with the default role [{ name: "Admin", value: "1" }].
// From lawyerUserController.js — registration handler
const pass = await encryptPassword(password);
const data_lawyer_user = new LawyerUser({
  email,
  password: pass,
  role: [{ name: "Admin", value: "1" }],
});
const new_user = await data_lawyer_user.save();

Login

Sending a POST request to /api/lawyer/user/login with email and password triggers:
  1. The server looks up the LawyerUser document by email (case-insensitive via .toLowerCase()).
  2. The submitted password is compared against the stored bcrypt hash via comparePassword().
  3. On success, jwt.sign() creates a token with the payload { _id, email, role }, signed with the SECRET environment variable, and set to expire in 365 days.
  4. The new token is persisted back to the LawyerUser document and returned in the response body.
// From lawyerUserController.js — login handler
const token = jwt.sign(
  {
    _id: userX._id,
    email: userX.email,
    role: userX.role,
  },
  config.SECRET,
  {
    expiresIn: "365d",
  }
);

JWT structure

A decoded token carries the following payload:
{
  "_id": "64a1f2c3e4b0d5f6a7b8c9d0",
  "email": "lawyer@despacho.com",
  "role": [
    { "name": "Admin", "value": "1" }
  ],
  "iat": 1700000000,
  "exp": 1731536000
}
FieldTypeDescription
_idstringMongoDB ObjectId of the LawyerUser document
emailstringThe lawyer’s registered email address
rolearrayArray of role objects { name, value } (see Roles)
iatnumberUnix timestamp — when the token was issued
expnumberUnix timestamp — when the token expires (iat + 365d)
Tokens expire after 365 days. Once a token expires, the Token middleware returns 403 with { msj: "Sesion finalizada", status: false }. The lawyer must call POST /api/lawyer/user/login again to obtain a fresh token.

Using the token

Every protected endpoint expects the token in the Authorization HTTP header using the Bearer scheme:
Authorization: Bearer <your_jwt_token>

curl example — login and use the token

# Step 1: Login and capture the token
curl -s -X POST https://api.despacho.example.com/api/lawyer/user/login \
  -H "Content-Type: application/json" \
  -d '{"email": "lawyer@despacho.com", "password": "mySecurePass"}' \
  | jq -r '.token'

# Step 2: Use the token to list pending reservations
curl -X POST https://api.despacho.example.com/api/form/reserve/list/reservation-false \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json"
Store the JWT securely on the client side. Do not persist it in localStorage in web browsers — use an HttpOnly cookie or a secure in-memory store to reduce exposure to XSS attacks. Never log or expose the raw token in client-side error reports.

Token middleware (Token)

The Token middleware in src/middleware/tools/segurity.js guards every lawyer-only route. It runs before the route handler and either calls next() to proceed or short-circuits the request with an error response. What it does, step by step:
  1. Reads the authorization header from the incoming request.
  2. Splits the header value on a space character and takes index [1] to isolate the raw token (stripping the Bearer prefix).
  3. If no token is found, responds immediately with 401 Unauthorized.
  4. Calls jwt.verify(token, config.SECRET, callback) to validate the signature and expiry.
  5. On a valid token, queries MongoDB for the LawyerUser document using the _id from the decoded payload. If no matching user is found, responds with 404 Not Found.
  6. Attaches { _id, email, role } to req.user and calls next().
// src/middleware/tools/segurity.js
import jwt from "jsonwebtoken";
import config from "../../config.js";
import { LawyerUser } from "../../models/LawyerUser.js";

export const Token = (req, res, next) => {
  const authHeader = req.headers["authorization"];
  const token = authHeader?.split(" ")[1];

  if (!token)
    return res.status(401).json({ msj: "Sin autorizacion", status: false });

  jwt.verify(token, config.SECRET, async (err, user) => {
    if (err) {
      if (err.message === "jwt expired")
        return res
          .status(403)
          .json({ msj: "Sesion finalizada", status: false });
      return res
        .status(403)
        .json({ msj: `${err.message}. Rechazo en la conexion`, status: false });
    }

    let lawyer_userX = await LawyerUser.findById(user._id);
    if (!lawyer_userX)
      return res
        .status(404)
        .json({ msj: "Usuario no encontrado", status: false });

    req.user = {
      _id: lawyer_userX._id,
      email: lawyer_userX.email,
      role: lawyer_userX.role,
    };
    next();
    return;
  });
};

Protected endpoints

The following reservation management endpoints require the Token middleware — any request without a valid bearer token will be rejected:
EndpointMiddleware
POST /api/form/reserve/accept/:reserveId/reserveToken
POST /api/form/reserve/list/reservation-trueToken, Paginate
POST /api/form/reserve/list/reservation-falseToken, Paginate
POST /api/form/reserve/list/reservation-allToken, Paginate
POST /api/form/reserve/remove/reservation/:reservationIdToken

Error responses

ScenarioStatusResponse body
No Authorization header / no token401{ "msj": "Sin autorizacion", "status": false }
Token expired403{ "msj": "Sesion finalizada", "status": false }
Token signature invalid or malformed403{ "msj": "<error>. Rechazo en la conexion", "status": false }
Token valid but user deleted from DB404{ "msj": "Usuario no encontrado", "status": false }

Roles

The role field on a LawyerUser document is an array of role objects, where each object has a name (human-readable label) and a value (numeric string identifier). This structure allows a single user to hold multiple roles simultaneously.
"role": [
  { "name": "Admin", "value": "1" }
]
Role namevalueDescription
Admin"1"Standard lawyer/administrator account. Assigned automatically on registration.
SuperAdmin"2"Elevated privileges for managing the system. Must be assigned manually.
The role array is embedded directly in the JWT payload, making it available to any downstream middleware or controller via req.user.role without an additional database round-trip.

Build docs developers (and LLMs) love