Sitelet https://github.com/plazasgiovanny/PoliMarket-Backend/tree/master/docs/Security
Skip to content

Latest commit

 

History

History

README.md

API de Seguridad - Módulo Security

Descripción General

El módulo de Seguridad proporciona endpoints para la gestión de usuarios y autenticación en el sistema PoliMarket. Implementa los requisitos funcionales RF01 (Gestión Centralizada de Autorizaciones) y RF02 (Inicio de Sesión de Usuarios).

Base URL

http://localhost:{puerto}/api/Security

Arquitectura Implementada (Simplificada - Sin MediatR)

  • Clean Architecture: Separación de capas (Domain, Application, Infrastructure, Presentation)
  • Service Layer: Servicios con lógica de negocio (SecurityService)
  • Repository Pattern: Abstracción del acceso a datos
  • Facade Pattern: SecurityController como punto de entrada unificado
  • Dependency Injection: Inyección de dependencias mediante interfaces
  • Principios SOLID: Aplicados en toda la implementación
Controller → ISecurityService → SecurityService → IRepository → Repository → DbContext

Autenticación

Por el momento, el sistema implementa autenticación básica (usuario y contraseña). Las credenciales se validan contra la base de datos y el password se almacena hasheado usando SHA256.

Endpoints Disponibles

1. Login (Inicio de Sesión)

2. Crear Usuario

3. Actualizar Usuario

4. Revocar Acceso de Usuario

5. Obtener Todos los Usuarios

6. Obtener Todos los Roles


📖 Documentación Detallada de Endpoints

Para información detallada de cada endpoint, consulte los siguientes documentos:


Requisitos Funcionales Implementados

RF01: Gestión Centralizada de Autorizaciones de Usuario

Endpoints relacionados:

  • POST /api/Security/users - Crear usuario
  • PUT /api/Security/users/{id} - Modificar usuario
  • PATCH /api/Security/users/{id}/revoke-access - Revocar acceso

Criterios de Aceptación:

  • ✅ CA 1.1: Usuario con rol "Vendedor Activo" puede iniciar sesión
  • ✅ CA 1.2: Usuario "Vendedor Inactivo" o "Suspendido" no puede acceder

RF02: Inicio de Sesión de Usuarios

Endpoint relacionado:

  • POST /api/Security/login

Criterios de Aceptación:

  • ✅ CA 2.1: Autenticación exitosa con credenciales válidas
  • ✅ CA 2.2: Error con contraseña incorrecta
  • ✅ CA 2.3: Error con usuario inexistente
  • ✅ CA 2.4: Carga de rol y permisos después del login

Códigos de Estado HTTP

Código Descripción
200 OK - Solicitud exitosa
201 Created - Recurso creado exitosamente
400 Bad Request - Datos inválidos
401 Unauthorized - Credenciales inválidas o usuario inactivo
404 Not Found - Recurso no encontrado
500 Internal Server Error - Error del servidor

Estructura de Respuestas de Error

Todas las respuestas de error siguen el siguiente formato:

{
  "message": "Descripción del error"
}

Ejemplos:

// Error de credenciales inválidas
{
  "message": "Usuario o contraseña inválidos"
}

// Error de usuario inactivo
{
  "message": "El usuario está inactivo o suspendido. No se permite el acceso."
}

// Error de username duplicado
{
  "message": "El nombre de usuario 'jperez' ya está en uso."
}

Roles del Sistema

Los roles disponibles controlan el acceso de los usuarios:

ID Nombre Descripción
1 Vendedor Activo Puede iniciar sesión y acceder al módulo de ventas
2 Vendedor Inactivo No puede iniciar sesión
3 Administrador Acceso completo al sistema

Flujo de Uso Típico

1. Crear un Usuario (RR.HH.)

POST /api/Security/users

2. Login del Usuario

POST /api/Security/login

3. Modificar Usuario (cambiar rol, etc.)

PUT /api/Security/users/{id}

4. Suspender Usuario (Revocar Acceso)

PATCH /api/Security/users/{id}/revoke-access

Consideraciones de Seguridad

Hashing de Contraseñas

Las contraseñas se hashean usando SHA256 antes de almacenarse en la base de datos. Nunca se almacenan en texto plano.

Nota: Para producción se recomienda usar algoritmos más robustos como BCrypt o Argon2.

Protección contra Enumeración de Usuarios

El endpoint de login devuelve el mismo mensaje de error tanto para usuario inexistente como para contraseña incorrecta, previniendo ataques de enumeración de usuarios.

Validación de Entrada

Todos los endpoints validan los datos de entrada antes de procesarlos.


Ejemplos de Integración

JavaScript (Fetch API)

// Login
async function login(username, password) {
  const response = await fetch('http://localhost:5000/api/Security/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ username, password })
  });
  
  if (response.ok) {
    const data = await response.json();
    console.log('Login exitoso:', data);
    return data;
  } else {
    const error = await response.json();
    console.error('Error de login:', error.message);
    throw new Error(error.message);
  }
}

// Crear usuario
async function createUser(userData) {
  const response = await fetch('http://localhost:5000/api/Security/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(userData)
  });
  
  return await response.json();
}

C# (HttpClient)

// Login
var client = new HttpClient();
var loginRequest = new { username = "jperez", password = "password123" };
var content = new StringContent(
    JsonSerializer.Serialize(loginRequest),
    Encoding.UTF8,
    "application/json"
);

var response = await client.PostAsync(
    "http://localhost:5000/api/Security/login",
    content
);

if (response.IsSuccessStatusCode)
{
    var result = await response.Content.ReadAsStringAsync();
    var loginResponse = JsonSerializer.Deserialize<LoginResponse>(result);
    Console.WriteLine($"Login exitoso: {loginResponse.FirstName}");
}

Python (requests)

import requests

# Login
def login(username, password):
    url = "http://localhost:5000/api/Security/login"
    payload = {
        "username": username,
        "password": password
    }
    
    response = requests.post(url, json=payload)
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(response.json()['message'])

# Uso
try:
    result = login("jperez", "password123")
    print(f"Login exitoso: {result['firstName']}")
except Exception as e:
    print(f"Error: {e}")

Testing con Postman/Thunder Client

Colección de Ejemplo

{
  "info": {
    "name": "PoliMarket - Security API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "Login",
      "request": {
        "method": "POST",
        "url": "{{baseUrl}}/api/Security/login",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"username\": \"jperez\",\n  \"password\": \"password123\"\n}"
        }
      }
    }
  ],
  "variable": [
    {
      "key": "baseUrl",
      "value": "http://localhost:5000"
    }
  ]
}

Troubleshooting

Error: "Connection string 'DefaultConnection' no está configurada"

Solución: Verificar que appsettings.json contenga la configuración de connection string.

Error: "Usuario o contraseña inválidos"

Posibles causas:

  1. Username incorrecto
  2. Password incorrecto
  3. Usuario no existe en la base de datos

Error: "El usuario está inactivo o suspendido"

Solución: El usuario tiene IsActive = false. Un administrador debe reactivarlo usando el endpoint de actualización.


Próximas Mejoras

  • Implementar JWT para autenticación stateless
  • Agregar refresh tokens
  • Implementar rate limiting
  • Agregar logging de intentos de login
  • Implementar bloqueo de cuenta después de múltiples intentos fallidos
  • Migrar a BCrypt o Argon2 para hashing de contraseñas

Soporte y Contacto

Para preguntas o reportar issues relacionados con el módulo de seguridad, contactar al equipo de desarrollo backend.