Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DragonesMagicos/ferromax_v0.8/llms.txt

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

Ferromax ERP uses JWT Bearer tokens for authentication. Obtain a token by posting credentials to /auth/login, then include it in the Authorization header of every subsequent request. Tokens are signed with HMAC-SHA and carry the user’s email, role, and internal ID as claims.

POST /auth/login

Authenticates a registered, active user and returns a signed JWT access token along with the user’s role and display name. Auth: None required

Request body

email
string
required
The registered email address of the user. Must be a valid email format.
password
string
required
The account password in plaintext. Compared against the BCrypt hash stored in the database.

Example request

curl -X POST http://localhost:8081/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "admin123"}'

Response 200 — Success

token
string
Signed JWT access token. Include this value as Bearer <token> in the Authorization header of all subsequent requests. Valid for 8 hours (28 800 000 ms) by default.
rol
string
The user’s assigned role. One of ADMIN, EMPLEADO, or CLIENTE.
nombre
string
The user’s first name, suitable for display in the UI.
mensaje
string
Human-readable success confirmation. Always "Login exitoso" on HTTP 200.
{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "rol": "ADMIN",
  "nombre": "José",
  "mensaje": "Login exitoso"
}

Response 401 — Invalid credentials

Returned when the email is not found, the account is inactive (activo = false), or the password does not match.
{
  "error": "UNAUTHORIZED",
  "mensaje": "Credenciales inválidas"
}
Accounts with activo = false are treated as non-existent. The login endpoint uses findByEmailAndActivoTrue, so disabled users always receive a 401 — not a 403.

POST /auth/register

Registers a new customer account. All self-registered users are automatically assigned the CLIENTE role — staff accounts with ADMIN or EMPLEADO roles must be provisioned directly in the database. Auth: None required

Request body

nombre
string
required
The user’s first name. Maximum 100 characters.
apellido
string
The user’s last name. Maximum 100 characters. Optional.
email
string
required
Email address for the new account. Must be a valid email format, maximum 150 characters, and unique across all users.
password
string
required
Plaintext password. Minimum 6 characters. Stored as a BCrypt hash — never logged or returned.

Example request

curl -X POST http://localhost:8081/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Valentina",
    "apellido": "Ríos",
    "email": "[email protected]",
    "password": "segura123"
  }'

Response 201 — Created

{
  "mensaje": "Usuario registrado exitosamente"
}

Response 400 — Email already registered

Returned when the submitted email already exists in the usuarios table.
{
  "error": "BAD_REQUEST",
  "mensaje": "El email '[email protected]' ya está registrado"
}
After registering, the user must call POST /auth/login to obtain a token. The register endpoint does not return a JWT.

GET /auth/me

Returns the full profile of the currently authenticated user by extracting the email claim from the submitted JWT, then fetching the latest data from the database. Auth: Bearer token required

Request

No request body. The token is read from the Authorization header.
Authorization: Bearer <token>

Example request

curl http://localhost:8081/api/auth/me \
  -H "Authorization: Bearer <token>"

Response 200 — User profile

id
Long
The user’s internal numeric ID in the database.
nombre
string
The user’s first name.
apellido
string
The user’s last name.
email
string
The user’s email address.
rol
string
The user’s current role: ADMIN, EMPLEADO, or CLIENTE.
{
  "id": 7,
  "nombre": "José",
  "apellido": "García",
  "email": "[email protected]",
  "rol": "ADMIN"
}

Response 401 — Missing or invalid token

{
  "error": "UNAUTHORIZED",
  "mensaje": "No autenticado"
}

Using Tokens in Requests

After a successful login the frontend stores the token and attaches it automatically to every outgoing request via an Axios interceptor defined in axiosClient.js. The same pattern applies to any HTTP client you use outside the frontend.
1

Call POST /auth/login

Post the user’s email and password. On success, save the returned token string.
2

Store the token

The React frontend persists the token in localStorage (key: token) via authService.js and exposes the authenticated user via AuthContext.jsx. Note that axiosClient.js reads the token from a separate localStorage key (ferromax_token) — these two keys co-exist independently in the frontend.
3

Attach the header

Include Authorization: Bearer <token> in every request to a protected endpoint. The Axios client does this automatically via a request interceptor.
4

Handle 401 responses

When the server returns 401, the token has expired or been invalidated. The Axios response interceptor clears the stored token and redirects the user to /login.

Axios client interceptor (axiosClient.js)

The following is the actual interceptor code from the Ferromax frontend. It reads the token from localStorage on every request and injects the Authorization header, and redirects to /login on any 401 response:
import axios from 'axios'

const axiosClient = axios.create({
  baseURL: '/api',
  headers: { 'Content-Type': 'application/json' },
  timeout: 15000,
})

// Adjunta el JWT en cada request si existe
axiosClient.interceptors.request.use((config) => {
  const token = localStorage.getItem('ferromax_token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

// Redirige al login cuando el servidor responde 401
axiosClient.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      localStorage.removeItem('ferromax_token')
      window.location.href = '/login'
    }
    return Promise.reject(error)
  },
)

export default axiosClient
Tokens expire after 8 hours (28 800 000 ms), as set by jwt.expiration in application.properties. There is no refresh endpoint — the user must call POST /auth/login again to obtain a new token after expiry.

JWT token claims

Every issued token contains the following custom claims in addition to standard JWT fields:
ClaimTypeDescription
subStringThe user’s email address (subject)
rolStringThe user’s role (ADMIN, EMPLEADO, CLIENTE)
usuarioIdLongThe user’s internal database ID
iatDateToken issued-at timestamp
expDateToken expiration timestamp
You can inspect these claims by decoding the token at jwt.io or by calling GET /auth/me while the token is still valid.

Build docs developers (and LLMs) love