Skip to main content

Overview

Mis Compras implements a dual authentication system using both PHP session-based authentication and client-side localStorage for maintaining user state across the application.
The platform uses PHP’s native session management for server-side authentication, while the frontend relies on localStorage for persisting user data.

Authentication Flow

Registration Flow

Users can register through either the Node.js or PHP backend:
1

User submits registration form

The client sends user credentials (name, email, password) to the backend
2

Password hashing

The backend hashes the password using bcrypt (Node.js) or PASSWORD_DEFAULT (PHP)
3

Duplicate check

The system verifies the email is not already registered
4

User creation

A new user record is created in the database
5

Success response

The client receives confirmation and can proceed to login

Login Flow

1

User submits credentials

Email and password are sent to the PHP login endpoint
2

User lookup

The system queries the database for the email
3

Password verification

The password is verified against the stored hash
4

Session creation

PHP creates a server-side session with user data
5

Client storage

User information is stored in localStorage for client-side access

Registration Endpoints

PHP Registration

curl -X POST http://localhost/php/registro.php \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "nombre=John Doe&[email protected]&contrasena=securepass123"
Request Parameters
ParameterTypeRequiredDescription
nombrestringYesUser’s full name
emailstringYesUser’s email address
contrasenastringYesUser’s password (will be hashed)
Success Response
{
  "success": true,
  "message": "🎉 ¡Registro exitoso!"
}
Error Responses
Missing Fields
{
  "success": false,
  "message": "⚠️ Faltan campos."
}
Duplicate Email
{
  "success": false,
  "message": "⚠️ Este correo ya está registrado."
}
Database Error
{
  "success": false,
  "message": "❌ Error al registrar el usuario."
}

Node.js Registration

curl -X POST http://localhost:4000/api/usuarios/registro \
  -H "Content-Type: application/json" \
  -d '{"nombre":"John Doe","correo":"[email protected]","contraseña":"securepass123"}'
Request Body (JSON)
FieldTypeRequiredDescription
nombrestringYesUser’s full name
correostringYesUser’s email address
contraseñastringYesUser’s password
Success Response
{
  "success": true,
  "message": "Usuario registrado con éxito"
}
Note the field name differences: PHP uses email and contrasena, while Node.js uses correo and contraseña.

Login Endpoint

PHP Login (Primary Method)

POST /php/login.php
curl -X POST http://localhost/php/login.php \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "[email protected]&contrasena=securepass123"
Request Parameters
ParameterTypeRequiredDescription
emailstringYesUser’s registered email
contrasenastringYesUser’s password
Success Response
{
  "éxito": true,
  "mensaje": "Inicio de sesión exitoso",
  "usuario": {
    "id": 1,
    "nombre": "John Doe"
  }
}
The PHP login endpoint uses Spanish field names (éxito instead of success). Ensure your frontend handles these correctly.
Error Responses
Missing Fields
{
  "éxito": false,
  "mensaje": "Faltan campos."
}
Invalid Password
{
  "éxito": false,
  "mensaje": "Contraseña incorrecta."
}
User Not Found
{
  "éxito": false,
  "mensaje": "Correo no registrado."
}

Session Management

Server-Side Sessions (PHP)

When a user successfully logs in, PHP creates a server-side session:
session_start();
$_SESSION["id_usuario"] = $usuario["id_usuario"];
$_SESSION["nombre"] = $usuario["nombre"];
Session Data Stored:
  • id_usuario: User’s database ID
  • nombre: User’s display name

Client-Side Storage (localStorage)

The frontend should store user data in localStorage for persistence:
// After successful login
const loginData = await response.json();

if (loginData.éxito) {
  localStorage.setItem('userId', loginData.usuario.id);
  localStorage.setItem('userName', loginData.usuario.nombre);
  localStorage.setItem('isLoggedIn', 'true');
}
Recommended localStorage Keys:
KeyDescriptionExample Value
userIdUser’s database ID"1"
userNameUser’s display name"John Doe"
isLoggedInLogin status flag"true"

Password Security

PHP Password Hashing

The PHP backend uses PHP’s native password hashing:
// Hashing (during registration)
$hash = password_hash($contrasena, PASSWORD_DEFAULT);

// Verification (during login)
if (password_verify($contrasena, $usuario["contrasena"])) {
    // Password is correct
}
  • Algorithm: bcrypt (via PASSWORD_DEFAULT)
  • Cost: Default (currently 10)
  • Salt: Automatically generated

Node.js Password Hashing

The Node.js backend uses bcrypt:
// Hashing (during registration)
const hash = await bcrypt.hash(contraseña, 10);

// Stored in database
await db.query(
  "INSERT INTO usuarios (nombre, correo, contraseña) VALUES (?, ?, ?)",
  [nombre, correo, hash]
);
  • Algorithm: bcrypt
  • Salt Rounds: 10
  • Library: bcrypt npm package
Both backends use bcrypt for password hashing, ensuring consistent security across the platform.

Authentication Best Practices

For Frontend Developers

  1. Always use HTTPS in production to prevent credential interception
  2. Clear localStorage on logout to prevent unauthorized access
  3. Validate session before sensitive operations by checking isLoggedIn flag
  4. Handle session expiration gracefully with appropriate error messages

For Backend Developers

  1. Never log passwords in console or error messages
  2. Use prepared statements for all database queries (already implemented)
  3. Implement rate limiting on login endpoints to prevent brute force attacks
  4. Consider adding email verification for new registrations
  5. Add CSRF protection for form submissions

Logout Implementation

While there’s no dedicated logout endpoint, implement logout as follows:

Frontend Logout

function logout() {
  // Clear all user data from localStorage
  localStorage.removeItem('userId');
  localStorage.removeItem('userName');
  localStorage.removeItem('isLoggedIn');
  
  // Optionally clear entire localStorage
  // localStorage.clear();
  
  // Redirect to login page
  window.location.href = '/login.html';
}

Backend Session Cleanup (PHP)

If you need to implement a PHP logout endpoint:
<?php
session_start();
session_destroy();
echo json_encode(["success" => true, "message" => "Sesión cerrada"]);
?>

Protected Routes

To protect routes that require authentication:

Frontend Route Protection

function checkAuth() {
  const isLoggedIn = localStorage.getItem('isLoggedIn');
  
  if (!isLoggedIn || isLoggedIn !== 'true') {
    // Redirect to login
    window.location.href = '/login.html';
    return false;
  }
  
  return true;
}

// Call on protected pages
checkAuth();

Backend Route Protection (Node.js Example)

// Middleware to check authentication
function requireAuth(req, res, next) {
  const userId = req.body.usuario_id || req.query.usuario_id;
  
  if (!userId) {
    return res.status(401).json({
      success: false,
      message: "Autenticación requerida"
    });
  }
  
  next();
}

// Use in routes
router.post("/checkout", requireAuth, async (req, res) => {
  // Handle checkout
});

Security Considerations

Current Security Limitations
  • No JWT tokens implemented
  • CORS allows all origins (*)
  • No session timeout mechanism
  • No account lockout after failed attempts
  • localStorage is vulnerable to XSS attacks
  1. Implement JWT tokens for stateless authentication
  2. Restrict CORS to specific frontend domains
  3. Add session timeouts (e.g., 30 minutes of inactivity)
  4. Rate limit login attempts (e.g., 5 attempts per 15 minutes)
  5. Use httpOnly cookies instead of localStorage for sensitive data
  6. Implement 2FA for enhanced security

Troubleshooting

Common Issues

Issue: “Faltan campos” error even with all fields provided
  • Verify you’re using application/x-www-form-urlencoded for PHP endpoints
  • Check field names match exactly (case-sensitive)
  • Ensure the request method is POST
Issue: Session not persisting across requests
  • Verify cookies are enabled in the browser
  • Check that session_start() is called at the beginning of PHP scripts
  • Ensure the session cookie domain is correctly set
Issue: Password verification always fails
  • Confirm the password field name matches (contrasena vs contraseña)
  • Verify the stored hash is valid in the database
  • Check that the password wasn’t accidentally hashed twice

Next Steps

Products API

Fetch and display product catalogs

Orders API

Process authenticated checkout

Users API

Manage user profiles

Configuration

Configure authentication settings

Build docs developers (and LLMs) love