Overview
DAF Backend implements a unique JWT-based authentication system that embeds database credentials directly in the token. This approach provides database-level security and audit trails, as each user connects to PostgreSQL with their own credentials.
Key Concept : Unlike traditional APIs with a single database user, DAF Backend creates database connections using credentials from the JWT token. This means authentication happens at both the API and database levels.
Authentication flow
The authentication process differs between POS and E-commerce systems:
POS system flow
User sends credentials
Client sends PostgreSQL database username and password to /api/pos/auth/login
API validates with database
Server attempts to connect to PostgreSQL using provided credentials
JWT token generated
If connection succeeds, a JWT token is created with credentials embedded
Subsequent requests use token
Client sends JWT in Authorization header, API extracts credentials and creates database connection
POS authentication endpoint Endpoint : POST /api/pos/auth/loginRequest body :{
"user" : "database_username" ,
"password" : "database_password"
}
Success response (200):{
"message" : "Login exitoso" ,
"token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c3VhcmlvIjoicG9zX3VzZXIiLCJwYXNzd29yZCI6InBvc19wYXNzd29yZCIsInJvbGUiOiJ1c3VhcmlvIiwiaWF0IjoxNzA5NTU2MDAwLCJleHAiOjE3MDk2NDI0MDB9.signature" ,
"role" : "usuario"
}
Error response (401):{
"message" : "Credenciales incorrectas o error de conexión" ,
"detail" : "password authentication failed for user \" pos_user \" "
}
E-commerce system flow
User registration
New users register with email, password, and client information via /api/ecom/auth/register
User login
Existing users login with email and password to /api/ecom/auth/login
JWT token generated
Server validates credentials against the usuario table and generates JWT with email and client code
Token used for requests
Client includes JWT in Authorization header for all protected endpoints
E-commerce registration endpoint Endpoint : POST /api/ecom/auth/registerRequest body :{
"email" : "[email protected] " ,
"password" : "SecurePass123" ,
"cli_ruc_ced" : "1234567890123" ,
"cliente" : {
"cli_nombre" : "Jane Smith" ,
"cli_telefono" : "0987654321" ,
"cli_celular" : "987654321" ,
"cli_direccion" : "456 Commerce Ave" ,
"ct_codigo" : "002"
}
}
Success response (201):"Usuario registrado exitosamente"
E-commerce login endpoint Endpoint : POST /api/ecom/auth/loginRequest body :Success response (200):{
"token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImN1c3RvbWVyQGV4YW1wbGUuY29tIiwiY2xpX2NvZGlnbyI6IkNMSTAwMSIsImlhdCI6MTcwOTU1NjAwMCwiZXhwIjoxNzA5NjQyNDAwfQ.signature"
}
JWT token structure
The JWT tokens have different payloads for POS and E-commerce systems:
POS Token Payload
E-commerce Token Payload
{
"usuario" : "pos_user" , // PostgreSQL username
"password" : "pos_password" , // PostgreSQL password
"role" : "usuario" , // User's database role
"iat" : 1709556000 , // Issued at timestamp
"exp" : 1709642400 // Expiration timestamp
}
Security Consideration : POS tokens contain database credentials. While encrypted, ensure tokens are transmitted only over HTTPS in production and stored securely on the client.
Using JWT tokens in requests
Once authenticated, include the JWT token in the Authorization header of all API requests:
cURL Example
JavaScript Fetch
Python Requests
curl http://localhost:3000/api/pos/cliente \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Authentication middleware
The API uses middleware to verify JWT tokens on protected routes:
POS Middleware
E-commerce Middleware
POS authentication middleware Located in src/middlewares/pos.auth.middleware.js: src/middlewares/pos.auth.middleware.js:4-33
const verifyToken = ( req , res , next ) => {
const authHeader = req . headers [ 'authorization' ];
if ( ! authHeader ) {
return res . status ( 401 ). json ({
message: 'Token no proporcionado' ,
});
}
const token = authHeader . split ( ' ' )[ 1 ]; // Authorization: Bearer {TOKEN}
if ( ! token ) {
return res . status ( 401 ). json ({
message: 'Token inválido' ,
});
}
try {
const decoded = jwt . verify ( token , process . env . JWT_SECRET );
// 🔒 Se mantiene compatibilidad con todo lo existente
req . user = decoded ;
next ();
} catch ( error ) {
return res . status ( 401 ). json ({
message: 'Token inválido o expirado' ,
});
}
};
The middleware:
Extracts token from Authorization: Bearer <token> header
Verifies token signature using JWT_SECRET
Decodes token and attaches payload to req.user
Rejects invalid or expired tokens with 401 status
E-commerce authentication middleware Located in src/middlewares/auth.middleware.js: src/middlewares/auth.middleware.js:3-11
module . exports = ( req , res , next ) => {
try {
const token = req . headers . authorization ?. split ( " " )[ 1 ];
req . user = jwt . verify ( token , process . env . JWT_SECRET );
next ();
} catch {
res . status ( 401 ). json ({ error: "Token inválido" });
}
};
This simplified middleware performs the same verification but with more concise error handling.
Credential-based database connections
The unique aspect of DAF Backend is how it uses JWT credentials to create database connections:
POS connection strategy
For POS endpoints, each request creates a new database connection using credentials from the JWT:
src/controllers/pos.cliente.controller.js:6-9
const connectFromJWT = ( req ) => {
const { usuario , password } = req . user ;
return getConnectionWithCredentials ( usuario , password );
};
The getConnectionWithCredentials function creates a connection pool:
src/config/db_pos.js:4-12
function getConnectionWithCredentials ( user , password ) {
return new Pool ({
host: process . env . POS_HOST ,
port: process . env . POS_PORT ,
database: process . env . POS_NAME ,
user ,
password ,
});
}
Connection Lifecycle : Each POS request creates a pool, executes queries, then closes the pool in the finally block. This ensures proper cleanup.
E-commerce connection strategy
E-commerce uses a traditional shared connection pool:
src/config/db_ecom.js:4-14
const pool = new Pool ({
host: process . env . EC_HOST ,
port: process . env . EC_PORT ,
database: process . env . EC_NAME ,
user: process . env . EC_USER ,
password: process . env . EC_PASSWORD ,
});
const getConnection = () => {
return pool ;
};
All e-commerce requests share this pool, as user identity is tracked at the application level via the JWT token.
POS login implementation
Here’s how the POS login controller validates credentials by attempting a database connection:
src/controllers/pos.auth.controller.js:4-58
const login = async ( req , res ) => {
const { user , password } = req . body ;
if ( ! user || ! password ) {
return res . status ( 400 ). json ({
message: 'user y password son requeridos' ,
});
}
try {
// Intentamos conectar a la BD con las credenciales que manda Postman
pool = getConnectionWithCredentials ( user , password );
// Verificamos todos los roles a los que pertenece el usuario
const result = await pool . query ( `
SELECT r.rolname
FROM pg_roles r
JOIN pg_auth_members m ON r.oid = m.roleid
JOIN pg_roles u ON u.oid = m.member
WHERE u.rolname = (SELECT CURRENT_USER)
` );
// Extraemos todos los nombres de roles en un array
const role = result . rows [ 0 ] ? result . rows [ 0 ]. rolname : 'usuario' ;
const token = jwt . sign (
{
usuario: user ,
password: password ,
role: role ,
},
process . env . JWT_SECRET ,
{
expiresIn: process . env . JWT_EXPIRES_IN ,
}
);
return res . status ( 200 ). json ({
message: 'Login exitoso' ,
token ,
role ,
});
} catch ( error ) {
return res . status ( 401 ). json ({
message: 'Credenciales incorrectas o error de conexión' ,
detail: error . message
});
} finally {
if ( pool ) {
await pool . end ();
}
}
};
If the database credentials are incorrect, the connection will fail and return a 401 error. This validates authentication at the database level.
Token expiration
Tokens expire after the duration specified in JWT_EXPIRES_IN environment variable (default: 24 hours).
When a token expires:
The middleware will return: {"message": "Token inválido o expirado"}
The client must re-authenticate by calling the login endpoint again
A new token will be issued with a fresh expiration
Implement token refresh logic in your frontend to automatically re-authenticate users before their tokens expire.
Protected routes
Routes are protected by adding the verifyToken middleware:
POS Route Protection (src/routes/pos.cliente.routes.js)
E-commerce Route Protection (src/routes/ecom.auth.routes.js)
const { verifyToken } = require ( '../middlewares/pos.auth.middleware.js' );
router . get ( '/' , verifyToken , clienteController . getAll );
router . post ( '/' , verifyToken , clienteController . create );
router . get ( '/:id' , verifyToken , clienteController . getByID );
Best practices
Secure token storage Store JWT tokens securely on the client (e.g., httpOnly cookies, secure localStorage)
HTTPS only Always use HTTPS in production to protect tokens in transit
Token rotation Implement token refresh before expiration for seamless user experience
Database permissions Grant POS database users only the permissions they need (principle of least privilege)
Common authentication errors
401: Token no proporcionado
The Authorization header is missing from the request. Solution : Include the header with format Authorization: Bearer <token>
The token format is incorrect or the Bearer prefix is missing. Solution : Ensure token follows format Bearer <token> in Authorization header
401: Token inválido o expirado
The JWT signature is invalid or the token has expired. Solutions :
Token may have expired - login again to get a new token
JWT_SECRET may have changed on the server
Token may be corrupted - request a new token
401: Credenciales incorrectas o error de conexión
For POS login: The database username/password is incorrect. Solutions :
Verify the PostgreSQL user exists: SELECT * FROM pg_roles WHERE rolname = 'username';
Check password is correct
Ensure user has CONNECT privilege on the database
Next steps
Architecture Understand how authentication fits into the overall architecture
Database Learn more about connection pooling and database setup
Error Handling Handle authentication errors gracefully
POS API Reference Explore all authenticated POS endpoints