Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Luisangelebp/SCO_Autolavados/llms.txt

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

The SCO Autolavados API uses JSON Web Tokens (JWT) for stateless authentication. The flow is straightforward: call the login endpoint with valid credentials, receive a signed access token and a refresh token, then include the access token in the Authorization header of every request to a protected route. No session state is kept on the server — each request is authenticated independently by verifying the token’s signature against JWT_SECRET.

Obtain a Token

Send a POST request to /api/users/login with an identifier (either the user’s registered email address or their user username field) and their password.
curl -X POST http://localhost:3000/api/users/login \
  -H "Content-Type: application/json" \
  -d '{"identifier": "admin", "password": "admin123"}'
Successful response — 200 OK:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "a1b2c3d4-...",
    "email": "[email protected]",
    "cedula": "V12345678",
    "role": {
      "id": "uuid-role",
      "name": "ADMIN"
    }
  }
}
The response contains both a short-lived access token (token, valid for 15 minutes) and a long-lived refresh token (refreshToken, valid for 7 days). Store both values — use token to authenticate API calls and refreshToken to silently obtain a new access token once it expires. The identifier field accepts either the user’s email or user (username) — the login controller resolves both automatically.

Using the Token

Include the access token as a Bearer credential in the Authorization header:
curl http://localhost:3000/api/users \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
The header must follow the exact format Bearer <token>. Any other format (missing scheme, extra whitespace, etc.) will be rejected with 401.

Refreshing an Expired Token

When the access token expires (after 15 minutes), call POST /api/users/refresh with the refresh token to obtain a new access token without re-entering credentials.
curl -X POST http://localhost:3000/api/users/refresh \
  -H "Content-Type: application/json" \
  -d '{"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}'
Successful response — 200 OK:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
The endpoint returns only a new token (access token). The refresh token itself is not rotated — the same refreshToken from the original login remains valid until it expires after 7 days. Error responses:
StatusScenario
401refreshToken field is missing from the request body
401Refresh token signature is invalid or it has expired
401The user account associated with the refresh token is inactive
The refresh token payload contains { id, isRefresh: true }. The server validates the isRefresh flag; supplying a regular access token to this endpoint will be rejected with 401.

Token Payload

When the verifyToken middleware receives a request it:
  1. Reads the Authorization header and checks that it starts with Bearer .
  2. Extracts the token string after the space.
  3. Calls jwt.verify(token, process.env.JWT_SECRET) to validate the signature and expiry.
  4. Attaches the decoded payload to req.user so downstream controllers can read it.
The decoded access token payload contains:
ClaimDescription
idUUID of the authenticated user
emailEmail address of the authenticated user (may be null for reception-created accounts)
cedulaNational ID / RIF of the authenticated user
roleRole name string (e.g. "ADMIN", "CUSTOMER", "LAUNDRER")
expUnix timestamp of token expiry (15 minutes after issuance)
iatUnix timestamp of token issuance
If the token is missing, malformed, or expired, verifyToken responds immediately with 401 and does not call next():
{
  "error": "Token inválido o expirado"
}

Role Enforcement

Routes that require a specific role are additionally guarded by verifyRole(allowedRoles). After verifyToken attaches req.user, verifyRole checks that req.user.role (case-insensitive) is in the allowedRoles array passed to the middleware.
// Example: ADMIN-only route
router.get('/users', verifyToken, verifyRole(['ADMIN']), async (req, res) => { ... });

// Example: ADMIN or CUSTOMER route
router.post('/payments', verifyToken, verifyRole(['ADMIN', 'CUSTOMER']), async (req, res) => { ... });
If the authenticated user’s role is not in the allowed list, the middleware returns 403:
{
  "error": "Acceso denegado. Se requiere uno de los siguientes roles: ADMIN"
}
If req.user or req.user.role is absent after token verification, the middleware returns 403:
{
  "error": "Acceso denegado. Rol no identificado."
}

Error Responses

StatusScenario
401Authorization header is missing or does not start with Bearer
401Token signature is invalid or the token has expired
401Wrong credentials supplied to POST /api/users/login
401Missing or invalid refreshToken supplied to POST /api/users/refresh
403Valid token, but the user’s role is not permitted for the requested endpoint

Token Storage

The SCO Autolavados frontend stores the JWT in localStorage after a successful login. This makes the token available across page refreshes and browser tabs. For production deployments that require higher security guarantees, consider migrating to httpOnly cookies so the token is not accessible from JavaScript, reducing exposure to XSS attacks.

Environment Configuration

The JWT_SECRET environment variable must be set before starting the server and must use the same value for both token generation (signing at login) and token validation (verifyToken middleware). A mismatch will cause every token verification to fail with 401. The server will refuse to start entirely if JWT_SECRET is absent from the environment.
Set the variable in your .env file at the project root:
JWT_SECRET=your_long_random_secret_here

Build docs developers (and LLMs) love