SDK viafirma platform

Uso Viafirma Desktop por protocolo - autenticación

Desde la versión 3.15 de viafirma platform se soporta una modalidad (inicialmente solo para windows) que permite utilizar directamente Viafirma Desktop (versión mínima: 1.6.0) invocando la aplicación por protocolo. Para ello, la estrategia reside en la preparación inicial de la operación mediante una invocación a servicios REST, devolviendo el servidor un código de operación y un enlace para abrir la aplicación por protocolo. Al abrirlo la aplicación pierde el control de lo que ocurre, por lo que debe iniciar un polling Javascript a otro servicio REST donde consulta el estado de la operación, sabiendo si está finalizada o no, con errores, etc. y se exponen funciones que son invocadas automáticamente (callback) en caso de error, éxito, cancelación, etc., pasando un objeto JSON con los datos de la operación.

Java

Podemos encontrar un ejemplo de uso de esta lógica de invocación directa en la aplicación de ejemplo.

Como se verá en ese ejemplo de código, se realiza una preparación de la operación, devolviendo el servidor un objeto con el código de operación y el enlace para abrir la aplicación.

//Obtenemos la instancia del cliente que previamente ha sido inicializado
ViafirmaClient viafirmaClient = ViafirmaClientFactory.getInstance();
// Now use the new prepareAuthForDirectDesktop method
AuthOperationRequest authRequest = new AuthOperationRequest();                                //authRequest.setAutoSend(true);
CertFilter certFilter = new CertFilter();
//Example: use only FNMT certificates
certFilter.setOperator(FilterOperator.contains);
certFilter.getFilterValues().add("FNMT");

//More chances: CA Filter, Number User Id Filter
CertFilter caFilter = new CertFilter();
caFilter.setOperator(FilterOperator.contains);
caFilter.getFilterValues().add("FNMT");

CertFilter numberUserIdFilter = new CertFilter();
numberUserIdFilter.setOperator(FilterOperator.contains);
numberUserIdFilter.getFilterValues().add("4");

//authRequest.setCertFilter(certFilter);
//authRequest.setCaFilter(caFilter);
//authRequest.setNumberUserIdFilter(numberUserIdFilter);


authRequest.setAutoSend(true);
authRequest.setSessionId(request.getSession().getId());
// The method returns an object with the information required to:
// a) Create a button that opens Viafirma Desktop by protocol
// b) Gets the just-prepared operation ID to start polling using Javascriot
DirectDesktopInvocation directCall = viafirmaClient.prepareAuthForDirectDesktop(authRequest);
String operationId = directCall.getOperationId();
String viafirmaDesktopLink = directCall.getViafirmaDesktopInvocationLink();

En este código fuente se ha creado un objeto que da propiedades concretas a la operación de autenticación, y se hace la llamada utilizando viafirma client, obteniendo, como se ve, el operationId y el link para abrir la aplicación. En ese objeto se pueden añadir tres tipos de filtros distintos: CA Filter (filtra por CAs emisoras de certificados), Number User Id (filtra por el serial number del certificado) y el genérico que filtra por cualquier valor dentro del certificado. El uso de los filtros de CA y Serial Number requiere una versión mínima de Viafirma Desktop = 1.6.7.

Dentro del objeto de autenticación se incluye el sessionId del usuario; para evitar riesgos de seguridad el sistema comprobará que la recuperación de los datos de la autenticación se haga con la misma sesión que se inició la operación. Nuestra página ubicará un enlace para abrir Viafirma Desktop por protocolo con ese enlace, e iniciará un proceso de polling Javascript. Para ello, debemos haber incluido código Javascript en nuestra página, como el siguiente:

<script src="<%=ConfigureUtil.getViafirmaServer() %>/viafirma.js?t=<%=System.currentTimeMillis()%>">
    // Including this remote Javascript is mandatory, it includes the polling logic
</script>
<script>
// Customize this in your own client webapp... this is just a sample!
// When the polling detects an error, it invokes this function
function showError(response) {
    document.getElementById("loading").innerHTML = "";
    document.getElementById("authError").innerHTML = "Ocurrió un problema durante la autenticación: "+ JSON.stringify(response);
}
                                 // If the user cancels the operation in Viafirma Desktop app, this function is invoked
function showCancel(response) {
    document.getElementById("loading").innerHTML = "";
    document.getElementById("authCancel").innerHTML = "La autenticación fue cancelada: "+ JSON.stringify(response);
}
                                 // If the authentication runs ok, this function is invoked - customize it with your own logic 
function showSuccess(response) {
    window.location.replace("./exampleAuthenticationViafirmaDesktopResult.jsp?operationId=" + response.operationId);
}
                                 // If Viafirma Desktop is not loaded, this function is invoked
function showUnloaded() {
    alert("Viafirma Desktop no encontrado");
     document.getElementById("loading").style = "display: none;";

      document.getElementById("authSuccess").innerHTML = 
      "<p>Viafirma Desktop no ha sido cargado, aquí se puede incluir código para gestionar la instalación, instrucciones, etc.</p>";
}
// Here we initialize the viafirma.js polling 
function initAuth() {
       document.getElementById("authButton").style = "display: none;";
       document.getElementById("loading").innerHTML = "<img src='../images/icons/ajax-loader.gif' />";

       // Start the viafirma JS client: watch the status of a given operationId
       // - if the operation fails, "errorCallback" will be called
       // - if the operation is cancelled, "cancelCallback" will be called
       // - if the operation is completed: "successCallback" will be called
       // - if Viafirma client is not loaded after unloadedTime seconds: "unloadedCallback" 
       viafirma.init({
           // Here we include 
           operationId: "<%=operationId%>",
           viafirmaUrl: "<%=ConfigureUtil.getViafirmaServer() %>/",
           unloadedTime: 5,
           errorCallback: function(response) {
               showError(response);
           },
           successCallback: function(response) {
               showSuccess(response);
           },
           cancelCallback: function(response) {
               showCancel(response);
           },
           unloadedCallback: function(response) {
               showUnloaded();
           }
       });
}
</script>

Obsérvese que se ha incluido una query param al cargar el Javascript remoto viafirma.js, para evitar posibles problemas de caché en los usuarios en el caso de que este Javascript se modifique en futuras versiones.

.NET

Podemos encontrar un ejemplo de uso de esta lógica de invocación directa en la aplicación de ejemplo aspx - aspx.cs

El código es muy similar al ejemplo anterior Java, realizando una preparación de la operación, devolviendo el servidor un objeto con el código de operación y el enlace para abrir la aplicación.

Code behind:

//Obtenemos la instancia del cliente que previamente ha sido inicializado
public async void Autenticar_ClickAsync(object sender, EventArgs e)
{
    // Iniciamos el proceso de autenticar redireccionando el usuario a Viafirma.
    ViafirmaClient clienteViafirma = ViafirmaClientFactory.GetInstance();
    AuthOperationRequest request = new AuthOperationRequest();
    request.AutoSend = true;
    desktopInvocation = await clienteViafirma.PrepareAuthForDirectDesktopAsync(request);
}

En este código fuente se ha creado un objeto que da propiedades concretas a la operación de autenticación, y se hace la llamada utilizando viafirma client, obteniendo, como se ve, el operationId y el link para abrir la aplicación. Nuestra página ubicará un enlace para abrir Viafirma Desktop por protocolo con ese enlace, e iniciará un proceso de polling Javascript. Para ello, debemos haber incluido código Javascript en nuestra página, como el siguiente:

                                <form id="form1" runat="server">    
                                <% if (desktopInvocation == null) { %>
                                    <p>
                                        <asp:button  ID="autenticarBoton" runat="server" 
                                                Text="Iniciar proceso de autenticación"  OnClick="Autenticar_ClickAsync" 
                                                Width="245px"  />
                                    </p>
                                    <% }
                                        else
                                        {
                                    %>
                                    <script src="<%=Viafirma.ViafirmaClientFactory.GetInstance().UrlPublica%>/viafirma.js">
                                         // Include this remote Javascript is mandatory, it includes the polling logic
                                    </script>
                                    <script>
                                        // Customize this in your own client webapp... this is just a sample!
                                        // When the polling detects an error, it invokes this function
                                        function showError(response) {
                                            document.getElementById("loading").innerHTML = "";
                                            document.getElementById("authError").innerHTML = "Ocurrió un problema durante la autenticación: " + JSON.stringify(response);
                                        }
                                        // If the user cancels the operation in Viafirma Desktop app, this function is invoked
                                        function showCancel(response) {
                                            document.getElementById("loading").innerHTML = "";
                                            document.getElementById("authCancel").innerHTML = "La autenticación fue cancelada: " + JSON.stringify(response);
                                        }
                                        // If the authentication runs ok, this function is invoked - customize it with your own logic 
                                        function showSuccess(response) {
                                            window.location.replace("./exampleAuthenticationViafirmaDesktopResult.jsp?operationId=" + response.operationId);
                                            // The server will be able to retrieve certificate validation using the operationId: 
                                            // viafirmaClient.getCertificateValidationResponse(operationId, sessionId); 
                                            // The session Id will be checked.

                                        }
                                        // Here we initialize the viafirma.js polling 
                                        function initAuth() {
                                            document.getElementById("authButton").style = "display: none;";
                                            document.getElementById("loading").innerHTML = "<img src='./images/icons/ajax-loader.gif' />";

                                            // Start the viafirma JS client: watch the status of a given operationId
                                            // - if the operation fails, "errorCallback" will be called
                                            // - if the operation is cancelled, "cancelCallback" will be called
                                            // - if the operation is completed: "successCallback" will be called
                                            viafirma.init({
                                                // Here we include 
                                               operationId: "<%=desktopInvocation.OperationId%>",
                                               viafirmaUrl: "<%=Viafirma.ViafirmaClientFactory.GetInstance().UrlPublica%>/",
                                               errorCallback: function (response) {
                                                   showError(response);
                                               },
                                               successCallback: function (response) {
                                                   showSuccess(response);
                                               },
                                               cancelCallback: function (response) {
                                                   showCancel(response);
                                               }
                                           });
                                        }
                                    </script>
                                    <p id="authError"></p>
                                    <p id="authCancel"></p>
                                    <p id="authSuccess"></p>
                                    <p id="loading"></p>
                                    <p id="authButton">
                                        <a class="button" href="<%=desktopInvocation.ViafirmaDesktopInvocationLink%>" onClick="initAuth();">Autenticar con Viafirma Desktop</a>
                                    </p>
                                    <% }
                                    %>
                                </form>

Obsérvese que, al igual que en el caso Java, se ha incluido una query param al cargar el Javascript remoto viafirma.js, para evitar posibles problemas de caché en los usuarios en el caso de que este Javascript se modifique en futuras versiones.

Especificaciones de objetos JSON de respuesta en callbacks

  • Si el polling falla recibiendo un HTTP status distinto de 200/OK -la operación no ha finalizado todavía-, el objeto response recibido en el callback de error sólo tendrá un campo "message" y el operationId. Si la operación está finalizada, el objeto será de este tipo:
    {
      "operationId": "12345678",
      "isFinished": true,
      "isCancelled": false,
      "hasErrors": true,
      "isSignature": false,
      "errorCode": "1",
      "errorMessage": "Error description"
    }
    

Los códigos de error son los mismos que con el resto del API. Son especialmente relevantes los códigos relacionados con los estados CADUCADO (código 104) y REVOCADO (código 107) de un certificado. Si la aplicación Viafirma Desktop tiene algún problema local que comunique al servidor, se recibirá un errorCode = 2.

  • Si la operación ha sido cancelada, el callback de cancelación recibe un JSON como el siguiente:
    {
      "operationId": "12345678",
      "isFinished": true,
      "isCancelled": true,
      "hasErrors": false,
      "isSignature": false
    }
    
  • Si la operación ha acabado con éxito, la operación recibe un JSON con todos los datos del certificado y el operationId. Esta información está en el callback Javascript successCallback, y debe hacerse llegar a la lógica de servidor. No es recomendable consumir un servicio REST interno con la información del certificado, dado que sería sencillo que un atacante impersonase a otro usuario invocando a dicho servicio, pasando información de una tercera persona. Lo recomendable es invocar a lógica de servidor con el ID de operacion, y desde la lógica de servidor utilizar el servicio de viafirma cliente determinado, o simplemente consumir el servicio REST de Platform para descargar dicha información.

Los datos incluidos en el JSON son:

  • operationId: ID de operación devuelto en el primer proceso de preparación de la operación
  • numberUserId: número de identificador del usuario (NIF, cédula...)
  • name: Nombre del usuario
  • surname1: Primer apellido
  • surname2: Segundo apellido
  • email: Email del usuario
  • ca: Autoridad de Certificación emisora (por ejemplo Fábrica Nacional de Moneda y Timbre)
  • shortCa: Autoridad de Certificación emisora - descripción corta (por ejemplo FNMT)
  • jobTitle: Cargo del usuario
  • type: Tipo de certificado
  • cn: Common Name
  • organization: Nombre de la organización / empresa del usuario
  • certificateProperties: lista de variables del certificado (en formato key/value)
  • isValidated: booleano - obtiene valor true si el certificado ha sido validado correctamente
  • isExpired: booleano - obtiene valor true si el certificado está caducado
  • isRevoked: booleano - obtiene valor true si el certificado está revocado

Otra opciones de customización

Para poder lanzar Viafirma Desktop, el usuario debe tener la aplicación instalada; si no la tiene, transcurridos unos segundos la plataforma redirigirá a la URL de descarga de la aplicación:

https://descargas.viavansi.com/viafirma/viafirmaWPFclientInstall/viafirma-desktop.exe

Este comportamiento se puede personalizar en la aplicación cliente, para poder mostrar algún tipo de indicación en la aplicación, redirigir a una URL distinta (por ejemplo, a una versión de Viafirma Desktop específicamente compilada para una organización), etc.

Para ello, en la invocación a viafirma.init() podemos pasar dos parámetros adicionales:

  • unloadedCallback: una función que recibirá un callback si la aplicación no se ha ejecutado y ha descargado los datos de la aplicación transcurridos N segundos, siendo N el parámetro unloadedTime.
  • unloadedTime: tiempo que debe transcurrir para invocar la llamada a unloadedCallback. Si no es especifica, por defecto el valor es 10 segundos.