Ayuda sobre productos BOLD:

Acceso SSO

Página:
< Volver

ATENCIÓN: El siguiente contenido es de uso avanzado y su utilización puede ocasionar daños irreparables en la configuración del sistema

Single Sign On (SSO) es una técnica con la cual se evita a los usuarios que ya han estado autenticados en un primer sistema (han introducido login y password) la necesidad de volver a introducirlo en otros sistemas a los que acceden desde el primero.

Acceso a portal de BOLD por Single Sign On

El funcionamiento en líneas generales es el siguiente:

  1. El usuario ya se ha autenticado la página web del portal origen
  2. En esta página dispone de un enlace que le permite acceder al portal de BOLD
  3. Al hacer clic, acceder a la página interna del portal de BOLD sin necesidad de volver a introducir credenciales

Configuración técnica

Ejemplo HTML de conexión SSO

Desde el código javascript de la página web es necesario interceptar el clic sobre el enlace y preparar el mensaje HTTP POST con los datos adecuados para que al traspasar el control al portal de BOLD, éste ya no pregunte por la credenciales del usuario.

El funcionamiento es el siguiente:

   1. Obtenemos los parámetros firmados.
   2. Hacemos un POST a http://<URL_PORTAL>/faces/admin/indexSSO.xhtml
   3. El Portal valida los parámetros firmados contra <GPSNodeURL>
   4. Si la validación es satisfactorio se accede al Portal.
   5. Si no se muestra un mensaje de error.

Código ejemplo y parámetros de la llamada

En el siguiente enlace se puede descargar un fichero HTML (TestSSO.html) con el código de ejemplo que deberá reimplementarse en el portal origen:

http://www.gps-plan.com/wiki/content/TestSSO.html (seleccionar botón derecho "Grabar como..." para obtener el código).
<head>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<script>
function postToUrl(path, params, newWindow) {
    //Null check
    var method = "post"; // Set method to post by default

    var documentObject = document;
    if( newWindow ) {
      var win=window.open('about:blank');
      if (!win) {
        alert(TRANS("Error: no se puede acceder a la pantalla (recuerde que debe permitir las ventanas emergentes en este sitio)"));
        return;
      }
      documentObject = win.document;
    }

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = documentObject.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    //Fill the hidden form
    if (typeof params === 'string') {
        var hiddenField = documentObject.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", 'data');
        hiddenField.setAttribute("value", params);
        form.appendChild(hiddenField);
    }
    else {
        for (var key in params) {
            if (params.hasOwnProperty(key)) {
                var hiddenField = documentObject.createElement("input");
                hiddenField.setAttribute("type", "hidden");
                hiddenField.setAttribute("name", key);
                if(typeof params[key] === 'object'){
                    hiddenField.setAttribute("value", JSON.stringify(params[key]));
                }
                else{
                    hiddenField.setAttribute("value", params[key]);
                }
                form.appendChild(hiddenField);
            }
        }
    }

  documentObject.body.appendChild(form);
  form.submit();
}

function connectSSO()
{
  gotoToPortal("TEST", "administrador", "user998871", 
    "http://localhost/gpsnode/portal/ws/prepareSSO", // URL que genera los datos de autenticación firmados
    "http://localhost:8080/portal_DemoTiendas/faces/admin/indexSSO.xhtml"  // URL base del portal 
  );
/*  gotoToPortal("HSP", "administrador", "user998871", 
    "http://localhost/gpsnode/portal/ws/prepareSSO", 
    ""http://192.168.1.56:8080/BOLDWeb/faces/admin/indexSSO.xhtml"
  );*/
}


function gotoToPortal(origin, userName, personCode, urlWS, portalUrl)
{
  var paramsSign = {
    origin: origin,
    destination: "BOLD PORTAL",
    functionCode: 0,
    userName: userName,
    personCode: personCode,
    companyCode: "",
    sessionInfo: {} // dummy session data
  };
  // Pedimos los datos de autenticación
  $.ajax({
    type: "POST",
    encoding: 'utf8',
    contentType: "application/json; charset=utf-8",
    url: urlWS,
    data: JSON.stringify(paramsSign),
    success: function(dataSSO){
      if( !dataSSO.ok ) {
        alert( dataSSO.err );
        return;
      }

      // Enviamos un POST a la URL del portal con los datos de autenticación
      postToUrl( portalUrl, { SSOParam: dataSSO.data }, true );
    }
  });
}
</script>
</head>

<body>

<button type="button" onclick="connectSSO()">Conectar al portal</button>

</body>


Básicamente lo que determina el procedimiento son los parámetros de la función gotoToPortal() que por este orden son:

  • origin: identificador del portal origen
  • userName: identificador de usuario con las credenciales actuales
  • personCode: código de la persona en el programa de RR.HH. y que deberá corresponderse on un identificador en BOLD
  • urlWS: url del webservice que retorna los parámetros de identificación codificados y encriptados (en esta documentación se incluye un ejemplo de posible implementación)
  • portalUrl: url donde está el portal de BOLD (actualmente es http://<URL_PORTAL>/faces/admin/indexSSO.xhtml)
  • functionCode: se trata de un número entero que indicará la primera página que se mostrará al usuario tras la redirección. Ver la siguiente sección.

Configuración de la redirección: functionCode

Por defecto, la página que se le mostrará al usuario será la de datos personales. Pero es posible redirigirlo hacia otras páginas en función de este parámetro. Esta configuración reside en el fichero BoldWebCfg.xml (ver Configuración (portal del empleado)) en la sección opcional siguiente:

<SSOFunctionCodes>
<![CDATA[
  2--redirect:w/personaldata.xhtml?pfriendly=true;
  3--redirect:w/contractListSQL.xhtml?pfriendly=true;
  4--redirect:plan/currentweek.xhtml?pfriendly=true;
  5--redirect:plan/currentmonth.xhtml?pfriendly=true;
  6--redirect:plan/printyearcalendar.xhtml?pfriendly=true;
  7--redirect:w/anualcounters.xhtml?pfriendly=true;
  8--redirect:w/incidencelist.xhtml?pfriendly=true;
  9--redirect:forms/edit_form_enter_licenses_holidays.xhtml?pfriendly=true;
  10--redirect:forms/my_tab_licenses_all.xhtml?pfriendly=true;
  11--redirect:forms/edit_form_cancel_licenses_holidays.xhtml?pfriendly=true;
  12--redirect:forms/cancel_my_tab_licenses_all.xhtml?pfriendly=true;
  13--redirect:forms/tab_search_advanced.xhtml?Class=5&Type=0&pfriendly=true;
]]>
</SSOFunctionCodes>

En el ejemplo anterior pasando un functionCode=6 enviará el usuario a la página con el calendario anual.

Nota: hay ciertas páginas (como la del buscador de formularios) a las que se rechazará redirigir a un usuario a menos que tenga un rol superior al de Empleado.

Implementación mínima necesaria en el portal origen

  • Es necesario trasladar el código del ejemplo a la tecnología utilizada en el portal origen
  • Habrá que reimplementar el webservice en urlWS en el portal origen (o copiar el código de su implementación ejemplo en nodejs)

Implementación del webservice urlWS en nodejs

Este webservice prepara la respuesta JSON (el código se apoya en algunas funciones complementarias no incluidas en la distribución estándard de nodejs):

router.post('/portal/ws/prepareSSO', function(req, res) {
  var origin       = CCM.wsGetParam(req, res, "origin");
  var destination  = CCM.wsGetParam(req, res, "destination");
  var functionCode = CCM.wsGetParamInt(req, res, "functionCode");
  var userName     = CCM.wsGetParam(req, res, "userName");
  var personCode   = CCM.wsGetParam(req, res, "personCode");
  var companyCode  = CCM.wsGetParam(req, res, "companyCode");
  var destinationURL;
  if (destination === "BOLD PORTAL") {
    destinationURL = "https://BOLD:8081/boldweb";
  }
  else {
    return CCM.wsReturnError(req, res, new Error("Invalid destination: " + destination), true);
  }
  var resultJSON = {
    origin: origin,
    destination: destination,
    destinationURL: destinationURL,
    data: {
        timestamp: (new Date()).toISOString(),
        userName: userName,
        companyCode: companyCode,
        personCode: personCode,
        functionCode: functionCode
      },
    signature: "signatura del camp data en utilitzant RSA-SHA256",
    urlCert: "URL opcional del certificat X509"
  };
  // Locate PK file
  var pkFile;
  if (origin === "TEST")
    pkFile = "test/test_data/privatekey.pem";
  else
    pkFile = path.join(CCM.getBOLDWebCfgDir(req), origin + ".pem");
  if (!BOLDXML_tools.fileExists(pkFile)) {
    logger.error("PK file not found! " + pkFile);
    return CCM.wsReturnError(req, res, new Error("SSO is not enabled for this origin: " + origin), true);
  }
  // Sign data
  var signature;
  try {
    resultJSON.signature = CertsMgr.signData(pkFile, JSON.stringify(resultJSON.data));
  } catch (err) {
    logger.error("Exception signing data: " + err);
    var msgerr = "Key is not installed or is invalid!";
    return CCM.wsReturnError(req, res, new Error(msgerr), true);
  }
  CCM.wsReturn(req, res, resultJSON);
});

Función que efectúa la firma y encriptación del JSON de la respuesta

CertsMgr.signData = function(keyPEMFile, dataString) {
  var pem = fs.readFileSync(keyPEMFile);
  var key = pem.toString('ascii');
  var sign = require('crypto').createSign('RSA-SHA256');
  sign.update(dataString);
  var sig = sign.sign(key, 'hex');
  return sig;
};

Básicamente lee el fichero con la clave privada del certificado (.pem) y genera una firma digital sobre el parámetro string. Cuando el portal de BOLD reciba este paquete de datos, podrá verificar esta firma utilizando la clave pública del certificado complementario correspondiente.

Testing de la funcionalidad

La mejor forma es partir del fichero gpsnode/test/TestSSO.html y trazar dicho código. Desde aquí se puede probar con diferentes functionCode de forma sencilla.

Es importante destacar que solo los usuarios con acceso por LDAP se podrán validar con Single Sign On.

En el caso de usuarios únicamente definidos en BOLD, existe un procedimiento que sólo se habilitat durante las pruebas de desarrollo en java inyectando directamente en el código el password del usuario (ver UserBean::SSOExecute)

Generación de certificados para pruebas

Online certificate generator: https://infotechinc.github.io/create-x509-certificate/

Obtener un fichero .pfx (el que usa IIS o .NET) a partir de los ficheros anteriores: https://stackoverflow.com/questions/808669/convert-a-cert-pem-certificate-to-a-pfx-certificate

Herramientas openssl para manipular certificados: https://sourceforge.net/projects/openssl/

Was this article helpful?
0 out Of 5 Stars
5 Estrellas 0%
4 Estrellas 0%
3 Estrellas 0%
2 Estrellas 0%
1 Estrellas 0%
5
How can we improve this article?
How Can We Improve This Article?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Contenido