EWD.js and VistA: REST interface

This article is the fourth in the series that describes the EWD.js / VistA environment that is created by running Christopher Edwards’ OSEHRA installer.  In this article I’m going to focus on the REST interface that will have been installed and made ready for use, and show how it makes use of the same back-end functions that were described in the previous article.

The EWD REST Server

The EWD.js REST interface is an Apache 2 Open Source application that is designed to interoperate with one or more instances of EWD.js.  It essentially provides two functions:

  • a REST interface to EWD.js-based methods, converting REST requests into corresponding digitally-signed EWD.js HTTP(S)-based web service requests;
  • a message routing facility, allowing a single EWD REST server to interface to multiple EWD.js servers that can be running both locally and remotely.

EWD REST Server Running As A Service

After Chris’s installer finished, it started an instance of the EWD REST server as a service – in fact the same service that runs EWD.js also runs the EWD REST server, so stopping and restarting the EWD.js service (as described in the previous article) also stops and restarts the EWD REST server.

The EWD REST Server Configuration

The EWD REST server is configured and started via a startup file that you’ll find at:

/home/osehra/node/ewdRest.js

You’ll see from this file that it has been configured to listen on port 8000 and run over SSL/HTTPS (it uses the same self-signed certificates as the EWD.js web server).

You’ll see two sections that define its configuration:

  • service: the back-end EWD.js service(s) that are accessible via REST requests;
  • server: the EWD.js server(s) to which messages can be routed.

EWD REST request URLs must be of the format:

  http(s)://domainName:port/serverName/serviceName/path[?queryString]

where:

  • domainName = the domain name/IP address of the REST server
  • port = the TCP port on which the REST Server is listening
  • serverName = the name of a server configuration section
  • serviceName = the name of a service configuration section
  • path = a path that maps to a specific method
  • queryString = an optional set of query string name/value pairs

The server section that is defined for your EWD.js/VistA system is as follows:

  server: {
    ec2: {
      host: 'localhost',
      port: 8080,
      ssl: true,
      secretKey: '$keepSecret!',
      accessId: 'VistAClient'
    }
  }

So just one server, named ec2, has been defined.

The service section that is defined for your EWD.js/VistA system is as follows:

  service: {
    vista: {
      module: 'VistARestServer',
      service: 'parse',
      contentType: 'application/json'
    }
  },

Again, just one service, named vista, has been defined.

Put this together and it means that REST requests that will be accepted and parsed by the EWD REST server on your system will be of the format:

https://ec2-99-99-99-99.compute-1.amazonaws.com:8000/ec2/vista/path[?queryString]

Referring back to the server configuration definition in ewdRest.js, you can see that a serverName of /ec2/ means that incoming requests will be routed to an EWD.js server whose hostname is localhost and is listening on port 8080 over SSL: in other words the EWD.js system that’s already running on your server.

Referring back to the service configuration definition, the serviceName of /vista/ means that the request URLs will be parsed and handled by a method named parse within a back-end EWD.js module named VistARestServer.js.  The contentType of application/json means that JSON responses will be returned from these REST requests.

How the EWD REST Server is Authorised to use the EWD.js Server

There’s one further critical part of the configuration: the secretKey and accessId parameters in the server configuration section.  In order for the EWD REST server to communicate with an EWD.js server, it must be registered as an authorised Web Service client, otherwise its HTTP requests will be ignored.  This involves defining a unique accessId on the EWD.js system and allocating to it:

  • a secretKey that must be used by the web service client to digitally sign all web service requests
  • one or more back-end Node.js modules (applications) that the web service client is allowed to access

You can use the EWD.js application named webSvcMgr to view and manage registered web service clients that can access your EWD.js system.  Put the following URL into your browser:

https://ec2-99-99-99-99.compute-1.amazonaws.com:8080/ewd/webSvcMgr/index.html

Login using the EWD.js management password:

keepThisSecret!

Select Manage Users from the menu and you’ll see one accessId defined: VistAClient. Click on this name and you’ll see its secretKey ($keepSecret!) and two modules (applications) that it’s allowed to access (VistADemo and VistARestServer).

If we look again at the EWD REST server’s configuration file, you’ll see this accessId and secretKey:

  server: {
    ec2: {
      host: 'localhost',
      port: 8080,
      ssl: true,
      secretKey: '$keepSecret!',
      accessId: 'VistAClient'
    }
  }

So the EWD REST server is authorised to access the EWD.js server, and it knows the accessId and secretKey needed to digitally sign the requests that it forwards to the EWD.js server.

The VistARestServer Module

Let’s go back and look at the service configuration in the /home/osehra/node/ewdRest.js file:

  service: {
    vista: {
      module: 'VistARestServer',
      service: 'parse',
      contentType: 'application/json'
    }
  },

This means that all incoming REST requests for the service /vista/ will be handled by the parse() method within the back-end module named VistARestServer.

You’ll find this module file at:

/home/osehra/node/node_modules/VistARestServer.js

You’ll see that it contains just one function named parse() within it. You’ll also see that this function contains some very simple parsing logic that tests the value of the path and invokes an associated function, eg:

var vista = require('VistADemo');

module.exports = {
  parse: function(ewd) {
    var path = ewd.query.rest_path.split('/');
    if (path[1] === 'initiate') {
      return vista.initiate(ewd);
    }
  ...etc

What this means is that if the following REST request is received:

https://ec2-99-99-99-99.compute-1.amazonaws.com:8000/ec2/vista/initiate

then the initiate() function in a module named VistADemo is invoked. You’ll find that module here:

/home/osehra/node/node_modules/VistADemo.js

If you remember from the previous article in this series that examined the VistA Demonstration EWD.js application, you’ll remember that this module – VistADemo.js – contained its back-end logic too.

The VistA Demo REST Services

Your EWD.js system has four REST methods defined that cover the three steps that were demonstrated in the EWD.js browser application:

  • logging into VistA using an Access and Verify Code
  • listing patients by name prefix
  • retrieving basic information for a patient

Logging Into VistA

For security reasons, the login process has been split into two REST methods that ensure that, even though the REST requests are being made over SSL, the Access and Verify Codes aren’t specified “in the clear” as name/value pairs in the REST Request’s Query String.

The process is as follows:

  • An initiate request is sent to the REST Server
  • The response from the EWD.js server contains two values: a randomly-generated key and a randomly-generated Authorization string.  The key will be used to encrypt the Access and Verify codes, while the Authorization string will be used as the Authorization header value for all subsequent REST requests;
  • An authenticate request is sent to the EWD REST server,  The encrypted Access and Verify code string is sent as the credentials name/value pair in the URL’s QueryString;
  • If the decrypted Access and Verify Codes are valid, the client is logged into VistA and the DUZ and several other associated values are returned in the response.  An EWD Session is started and linked to the Authorization value;
  • If, for whatever reason, the request was invalid, a 401 error is returned and the Authorization value is invalidated so that it cannot be re-used.

Encryption uses the aes-256-cbc algorithm (though any other cipher supported by OpenSSH could be used instead).

Example Log In

Let’s try it out.  In order to do this, you’ll need to install a REST Client.  If you’re using the Chrome Browser, there’s a very good, free extension that you can installed – go into the Tools/Extensions menu and search for Advanced REST Client.

After you’ve installed and fired up the REST Client, enter the following URL:

https://ec2-99-99-99-99.compute-1.amazonaws.com:8000/ec2/vista/initiate

Modify the domain name to match that of your EC2 server.

You should see a JSON response containing:

{
Authorization: "thaHj7moMJnKy1H9ShPBbndL02z5V"
key: "onJxm2arRddicuRoU8EFzo8LRoGnG"
}

The actual values you get will be different from the ones above, and will be different each time you submit an initiate request.

The next step would normally happen programmatically within the back-end logic of an application, but here we’re going to manually encrypt an Access and Verify Code pair and send the resulting credentials value attached to an authenticate request.

In order to simplify this step, you’ll find that an EWD.js application named ewdEncrypter has been installed on your system.  Fire this application up in another tab on your browser using the URL (after appropriately adjusting the domain name):

https://ec2-99-99-99-99.compute-1.amazonaws.com:8080/ewd/ewdEncrypter/index.html

In the form that appears, enter the Access and Verify Codes as follows:

Access Code: fakedoc1
Verify Code: 1Doc!@#$

Copy and paste the key from the response for your initiate request and then click the Encrypt button. The encrypted value will appear in the credentials field below the Encrypt button. Copy this value and now put the following URL into your REST client (adjust the domain name and credentials value appropriately):

https://ec2-99-99-99-99.compute-1.amazonaws.com:8000/ec2/vista/authenticate?credentials=2f0c7fc5255592b84feaed568d087be0d21dfdf46681bfcdce0e342be05c5cbbccdafe05acce36c4ebaac226a68ad058

Before you send this, you’ll also need to tell the REST Client to add an Authorization header, and copy and paste the Authorization value from the response that you got back from your initiate request. Click the Send button and you should get back a response as follows:

{
DT: 3140302
DUZ: 51
displayName: "ROBERT ALEXANDER"
greeting: "Good evening ALEXANDER,ROBERT"
username: "ALEXANDER,ROBERT"
}

You’ve just logged into VistA using a secure REST request!

How the Authenticate Request Worked

We’ll now take a look at how this authenticate request actually worked.  As we saw earlier, the parse() method in VistARestServer.js was invoked:

var vista = require('VistADemo');

module.exports = {
  parse: function(ewd) {
    var path = ewd.query.rest_path.split('/');
    if (path[1] === 'initiate') {
      return vista.initiate(ewd);
    }
    if (path[1] === 'authenticate') {
      return vista.login(ewd);
    }
  ...etc

In other words, the authenticate path results in the login() method being invoked within the VistADemo module.

So, now examine the file:

/home/osehra/node/node_modules/VistADemo.js

and look for that login() function. You’ll find it at line 169.
After checking the validity of the Authorization header value and successfully decrypting the credentials string to obtain the original Access and Verify Codes, just look what it then invokes at line 197:

var results = VistALogin(credentials.accessCode, credentials.verifyCode, ewd);

If you remember from the previous article, this is exactly the same function that was used to authenticate the Access and Verify Codes when entered into the VistADemo EWD.js application! All that we’ve done is applied a slightly different wrapper around the same back-end code to turn it into a REST Service.

After it successfully logs us in, we just return the outputs object and it is sent back to the REST client as the response.

Identifying Patients By Name Prefix

Now that the client has successfully logged in, we can now invoke the patientsByName REST method.  Note that for security reasons, the Authorization value is only valid for 5 minutes between each response, so you may need to start again with an initiate request followed by an authenticate request.

Enter the following URL into your REST client (after adjusting the domain name appropriately):

https://ec2-23-23-58-52.compute-1.amazonaws.com:8000/ec2/vista/patientsByName?prefix=s

Ensure the Authorization header value is set correctly and click the Send button. You should get a JSON response containing an array of matching patients, eg:

[0:  {
id: 3
text: "SEVEN,PATIENT G"
},
1:  {
id: 16
text: "SEVENTEEN,PATIENT Q"
},
2:  {
id: 7
text: "SIX,PATIENT F"
},
3:  {
id: 17
text: "SIXTEEN,PATIENT P"
}
]

Now let’s see how this works. Look in /home/osehra/node/node_modules/VistARestServer.js and you’ll see the parsing logic for the patientsByName path:

    if (path[1] === 'patientsByName') {
      return vista.getPatientsByNamePrefix(ewd);
    }

Now look in /home/osehra/node/node_modules/VistADemo.js for the getPatientsByNamePrefix function. You’ll find it at line 214. You’ll see that once again, it makes use of the same core function that was used by the VistADemo EWD.js browser application when finding matching patients. See line 225:

     var results = getPatientsByName(ewd.query.prefix, 1000, ewd)

Get Patient Details

Finally, see if you can trace how the patientSummary REST method works and see how it uses the same core function as the EWD.js VistADemo application. Here’s the REST URL to try in your REST Client:

https://ec2-99-99-99-99.compute-1.amazonaws.com:8000/ec2/vista/patientSummary?id=17

Conclusions

The EWD REST Server is extremely powerful and secure, yet simple to use,  configure and adapt.  The ability to re-use the same back-end code as that used by EWD.js browser applications is a potential game-changer and huge time-saver, and clearly results in much lower maintenance overhead.  No more reinvention of wheels, and no more duplication of effort using different and incompatible technologies.

Although your REST Server has been configured to connect to just one local EWD.js Server, you can easily add as many other EWD.js servers to the server configuration section of the startup file.  Your EWD REST server would need to be authorised to use each EWD.js server via an associated accessId and secretKey.  In theory one EWD.js server could easily provide a federated REST service for all 134 of the VA’s VistA servers!  Additionally, several REST Servers could be set up , potentially at different locations, and each could be configured to access those same 134 VistA servers.   Thus a highly scalable and redundant architecture could easily be constructed.

This concludes our look at the EWD REST Server.  In the next and final article in this series, we’ll install the new browser-based EWD VistA Terminal and see how it can be used to integrate the old roll and scroll applications with our new responsive browser applications.

 

 

 

 

 

 

One comment

  1. There’s no no excuses left – try out EWD.js with VistA for yourself: it only takes 30 … https://robtweed.wordpress.com/2014/03/02/ewd-js-and-vista-rest-interface/.

Leave a reply to Jacob Cancel reply