Integración de Acceso Directo a Sistemas Externos mediante Credenciales Conocidas

En el desarrollo de aplicaciones modernas, es una necesidad común permitir a los usuarios "saltar" directamente a sistemas o plataformas de terceros desde nuestra propia aplicación, utilizando credenciales que ya gestionamos o conocemos. Esta funcionalidad, aunque a veces se asemeja a un Single Sign-On (SSO) rudimentario, difiere en que no siempre se basa en protocolos estandarizados. La complejidad de lograr esta integración depende en gran medida de la arquitectura de autenticación del sistema objetivo.

  1. Análisis de Métodos de Conexión

1.1. Mediante Envío Directo de Formulario o Redirección

Algunos sistemas externos, especialmente aquellos con implementaciones más antiguas o simplificadas, podrían permitir el inicio de sesión a través del envío directo de un formulario HTML. Si se puede identificar la URL de acción del formulario y los nombres de los campos para el usuario y la contraseña, es concebible intentar realizar una solicitud POST directa a ese endpoint con las credenciales predefinidas. Una alternativa es incrustar el sistema en un <iframe>, aunque esta práctica se ve cada vez más limitada por cuestiones de seguridad.

Sin embargo, este enfoque presenta serias limitaciones:

  • Las políticas de seguridad del navegador, como la directiva SameSite para cookies, pueden impedir que el sistema externo reconozca la sesión de autenticación si el envío ocurre desde un contexto de terceros.
  • La mayoría de los sistemas modernos incorporan medidas como tokens CSRF (Cross-Site Request Forgery) o validaciones de encabezados que frustran los intentos de envío directo no autorizados.
  • Esta técnica es inherentemente frágil y poco confiable para la mayoría de las plataofrmas actuales debido a las implicaciones de seguridad.

1.2. Inicio de Sesión a Través de API y Redirección (Desde el Cliente)

Una aproximación más contemporánea implica el uso de una API de autenticación proporcionada por el sistema externo. La secuencia de acciones en nuestra aplicación sería la siguiente:

  1. Realizar una llamada (por ejemplo, con AJAX o la API Fetch) al endpoint de autenticación del sistema externo, enviando el nombre de usuario y la contraseña.
  2. Si la autenticación es exitosa, el API externo debería responder con un indicador de éxito, un token de sesión, o información relevante.
  3. Una vez confirmada la autenticación, la aplicación propia redirige al navegador del usuario a la URL principal del sistema externo, esperando que el token de sesión (si se maneja a través de cookies HTTP) sea automáticamente reconocido.

El obstáculo más significativo en esta estrategia es la política de seguridad web Cross-Origin Resource Sharing (CORS). Si la solicitud AJAX se origina desde un dominio diferente al del sistema externo, el navegador bloqueará la lectura de la respuesta por motivos de seguridad. Aunque la solicitud al servidor externo puede haber tenido éxito, el cliente no podrá acceder a los datos de respuesta. Intentar manipular encabezados HTTP como Referer desde JavaScript para eludir CORS no es una solución viable, ya que los navegadores restringen estrictamente tales modificaciones por motivos de seguridad.

  1. Solución Robusta: Implementación de un Proxy Inverso con Nginx

Para superar las restricciones de CORS de forma efectiva, especialmente cuando no tenemos control sobre la configuración CORS del sistema externo, la solución más sólida es implementar un proxy inverso a nivel de infraestructura, como Nginx. Con un proxy inverso, todas las solicitudes de los usuarios de nuestra aplicación se dirigen inicialmente a un único punto de entrada (el servidor Nginx). Nginx actúa entonces como un intermediario inteligente:

  • Si una solicitud coincide con una ruta de nuestra aplicación, Nginx la reenvía a nuestro servidor de aplicación.
  • Si una solicitud coincide con una ruta designada para el sistema externo, Nginx la reenvía al servidor de dicho sistema.

Desde la perspectiva del navegador, todas las comunicaciones se establecen con un único dominio (el del proxy Nginx), eliminando así las preocupaciones relacionadas con CORS, ya que el navegador no detecta un cambio de origen. Nginx, en su rol de proxy, no aplica las políticas de origen cruzado; simplemente retransmite el tráfico entre el cliente y los servidores destino.

Ejemplo de Autenticación y Redirección desde el Frontend

El siguiente código ilustra cómo una aplicación de frontend podría iniciar una solicitud de autenticación a un API externo, asumiendo que un proxy Nginx ya está configurado para manejar las peticiones de origen cruzado. Este ejemplo utiliza jQuery, reestructurando el código original para mayor claridad y añadiendo manejo de errores.


<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Acceso a Plataforma Externa</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
        body { font-family: sans-serif; margin: 20px; }
        button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; }
        button:hover { background-color: #0056b3; }
    </style>
</head>
<body>

    <h1>Panel de Control de la Aplicación Propia</h1>
    <p>Utilice este botón para acceder directamente al sistema de gestión externo.</p>
    <button id="accederSistemaExternoBtn">Ir al Sistema de Gestión</button>

    <script type="text/javascript">
        $(document).ready(function() {
            $('#accederSistemaExternoBtn').on('click', function() {
                console.log("Iniciando solicitud de autenticación al sistema externo...");

                $.ajax({
                    type: "POST",
                    url: "/api-ext/login", // Esta URL será interceptada y redirigida por Nginx
                    dataType: "json",
                    data: {
                        user_id: "admin",
                        secure_pass: "SU_CONTRASEÑA_AQUI" // Manejar credenciales de forma segura
                    },
                    success: function (response) {
                        if (response && response.status === "success") { // Adaptar 'status' según el API externo
                            console.log("Autenticación exitosa. Redirigiendo al panel.");
                            window.location.href = "/panel-externo/dashboard"; // Nginx redirigirá esta ruta
                        } else {
                            alert("Fallo la autenticación: " + (response.message || "Credenciales inválidas o error desconocido."));
                            console.error("Respuesta del servidor externo:", response);
                        }
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        console.error("Error en la autenticación AJAX:", textStatus, errorThrown, jqXHR);
                        alert("No se pudo completar la autenticación. Por favor, intente de nuevo más tarde.");
                    }
                });
            });
        });
    </script>
</body>
</html>

Fragmento de Configuración de Nginx para Proxy Inverso

Este ejemplo muestra cómo configurar Nginx para actuar como un proxy inverso, dirigiendo las solicitudes a la aplicación propia y al sistema externo. Los encabezados proxy_set_header son cruciales para asegurar que el servidor destino reciba información de host y IP correcta.

server {
    listen 80;
    server_name tu.dominio.com; # El dominio de tu aplicación

    # Bloque para servir tu propia aplicación
    location / {
        proxy_pass http://localhost:8080/; # Dirección interna de tu servidor de aplicación
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Bloque para proxificar el API de autenticación del sistema externo
    location /api-ext/login {
        proxy_pass http://api.sistema-externo.com/auth/v2; # URL real del API de autenticación del sistema externo
        proxy_set_header Host api.sistema-externo.com; # Es vital para que el sistema externo reconozca el host
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # Si el API externo requiere cookies, podrías necesitar:
        # proxy_cookie_domain api.sistema-externo.com tu.dominio.com;
    }

    # Bloque para proxificar el acceso al panel o interfaz del sistema externo
    location /panel-externo/ {
        proxy_pass http://panel.sistema-externo.com/dashboard/; # URL real del panel externo
        proxy_set_header Host panel.sistema-externo.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # Considerar si necesitas reescribir URLs en el cuerpo de la respuesta o en JS
        # sub_filter_once off;
        # sub_filter 'panel.sistema-externo.com' 'tu.dominio.com/panel-externo';
    }

    # Puedes añadir más bloques 'location' según las rutas específicas
    # del sistema externo que necesites exponer o proxificar.
}

  1. Consideraciones Adicionales

Es fundamental comprender que esta metodología tiene limitaciones. Si el sistema externo implementa mecanismos de seguridad avanzados como CAPTCHAs, autenticación multifactor (MFA), o validaciones de sesión que requieren una interacción directa y compleja del usuario (por ejemplo, JavaScript que se ejecuta en el dominio original del sistema), un simple proxy o una simulación de login podrían no ser sufiicentes. En tales escenarios, una integración exitosa podría requerir el uso de protocolos SSO estandarizados como OAuth2 u OpenID Connect, si el sistema externo los soporta.

Etiquetas: Nginx Proxy Inverso CORS cross-origin JavaScript

Publicado el 7-12 09:47