rpcbroker.js installation & reference guide

22
RPCBroker.js Installation & Reference Guide Version 2 28 January 2016 © 2016 M/Gateway Developments Ltd RPCBroker.js Page 1

Upload: others

Post on 24-Oct-2021

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: RPCBroker.js Installation & Reference Guide

RPCBroker.js

Installation &Reference Guide

Version 228 January 2016

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �1

Page 2: RPCBroker.js Installation & Reference Guide

RPCBroker.js

Introduction

RPCBroker.js is a Free, Open Source EWD.js Custom Extension that provides secure and very high-performance access to all RPCs within the US Dept of Veterans Affairs’ (VA) Electronic Healthcare Record (EHR) known as VistA. It is intended to provide a modern, 21st Century replacement for VistA’s RPC Broker.

RPCBroker.js is written in JavaScript and runs under the control of EWD.js within the Node.js environment. It uses the stateless architecture provided by EWD.js, but behind the scenes it makes use of the EWD.js Session architecture to maintain each user’s Mumps symbol table. This means that the VistA RPCs run within the correct run-time context for each individual user: VistA RPCs are unaware that they aren’t running within their expected legacy stateful environment, and yet all the performance and scalability benefits of a modern stateless architecture can be achieved.

RPCBroker.js provides two methods of access to VistA’s RPCs:

- using REST requests over HTTP(S)- using web socket messages within EWD.js applications

In both cases, RPCs can either be invoked directly from the REST client or browser, or indirectly from the EWD.js back-end environment. This latter mechanism allows you to perform your own pre- and post- processing of RPCs, and to invoke multiple RPCs from one REST request or web socket message. In the case of the REST interface, you do this by defining your own set of custom REST request URLs.

RPCBroker.js therefore allows you to access VistA using its well-understood and tried-and-tested RPCs, but also allows you to customise their use and build on their behaviour, and, in conjunction with EWD.js, provides the means by which you can begin to modernise VistA and make it available as an SOA environment and/or via browser-based and mobile applications.

As its name implies, RPCBroker.js is a JavaScript technology that is primarily designed for use by JavaScript developers. However, through EWD.js you also have access to the Mumps environment if needed, and the REST interface can be used from any client running any other language.

AcknowledgementsRPCBroker.js has been inspired by, and builds upon the work of a number of key people and organisations. In particular, it builds on the pioneering work by Nikolay Topalov. I strongly recommend that you take a look at his excellent RPC-related projects for EWD.js which provide a great mechanism for exploring and trying out RPCs, and discovering their interface details. See:

https://github.com/nikolaytopalov

Also read his blog, particularly this article:

https://nikolaytopalov.wordpress.com/2014/02/25/calling-vista-remote-procedure-call-in-ewd-js/

I also wish to thank Joel Mewton who, of course, is one of the key developers behind MDWS. The REST and web-socket interfaces to RPCs were strongly influenced by discussions I had with him whilst collaborating on a project that was being managed by SAN Business Consultants during

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �2

Page 3: RPCBroker.js Installation & Reference Guide

2015. The ideas and techniques that were developed for that project (known as RAPTOR) to integrate a PHP-based front-end with VistA via EWD.js formed the basis of RPCBroker.js. My sincere thanks to Andrew Casertano and Frank Font from SAN Business Consultants for including me in that project. Its deliverables were released as Open Source by the VA. See:

https://github.com/VHAINNOVATIONS/RAPTOR

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �3

Page 4: RPCBroker.js Installation & Reference Guide

Getting Started with RPCBroker.js

1. Installation:

First ensure that you’ve installed the very latest build of EWD.js (build 111.0 or later).

Then:

cd ~/ewdjs (or wherever you’ve installed EWD.js)

npm install ewd-vista-rpc ewd-vista-security ewd-vista-handlers ewd-vista-rest

2. Edit your EWD.js startup file if you want REST access to RPCBroker.js

To configure EWD.js for use with RPCBroker.js’ REST interface, you need to amend your EWD.js startup file as follows:

a) tell EWD.js to load the child process custom module named ewd-vista-handlers by adding to the params object the following:

childProcess: { customModule: ‘ewd-vista-handlers’ }

b) Ensure that the custom REST URL interception module (ewd-vista-rest) is loaded into the master process. Additionally, for initial testing, ensure that Access Code and Verify Code encryption is disabled

Do this by adding the following callback into your ewdjs.start() function:

ewdjs.start(params, function() { ewd.customObj = { encryptAVCode: false }; require('ewd-vista-rest');});

For example, here is a complete example of an EWD.js startup file that :

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �4

Page 5: RPCBroker.js Installation & Reference Guide

var ewdjs = require('ewdjs');

var params = { poolSize: 2, httpPort: 8080, traceLevel: 3, database: { type: 'cache', path:"/opt/cache/mgr", username: "_SYSTEM", password: "SYS", namespace: "VISTA" }, management: { password: 'keepThisSecret!' }, childProcess: { customModule: 'ewd-vista-handlers' }};

ewdjs.start(params, function() { ewd.customObj = { encryptAVCode: false }; require('ewd-vista-rest');});

3. Install the Mumps RPC interface wrapper routine

You’ll find this in ~/node_modules/ewd-vista-rpc/mumps. It’s named ewdjsVistARPC.m

If you’re using Cache, the easiest way to install this is:

- open Studio - Switch to the namespace in which EWD.js runs - Click the New Button - Select Cache ObjectScript Routine - Copy and paste the contents of ewdjsVistARPC.m into the empty Studio window - Click the Compile Button on the top ribbon bar (first button on the right-hand set of buttons) - Save it as ewdjsVistARPC.mac or ewdjsVistARPC.int - either will do

If you’re using GT.M, copy the ewdjsVistARPC.m file to a directory that has been configured for routine access.

4. Install the Mumps Utilities Routine for EWD.js

If you haven’t already installed this as part of your EWD.js system, you’ll find it in ~/node_modules/ewdjs/extras/mumps. It’s named ewdjsUtils.m

For Cache, repeat the steps in 3) but ensure you save the routine as ewdjsUtils

5. Start Up EWD.js as normal using your edited startup script.

eg node startVistA

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �5

Page 6: RPCBroker.js Installation & Reference Guide

if you’re using Cache on Linux, you may need to add sudo, depending on how you’ve set permissions for Cache:

sudo node startVistA

You should now be ready to try using the RPCBroker.js interface

You can now login to and access VistA using standard RPC calls in two ways: - as REST requests - via EWD.js WebSocket Messages

Note that if you only want to access VistA RPCs via EWD.js web socket messages, you only need to follow steps 1, 3 and 4. Indeed, step 1 can be reduced to simply:

npm install ewd-vista-rpc

You can use this module with EWD.js applications without any change to your EWD.js startup file.

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �6

Page 7: RPCBroker.js Installation & Reference Guide

Accessing RPCBroker.js via REST

Try it OutFor testing purposes, I’d recommend that you install and use a REST client such as the Chrome Extension named Advanced REST Client.

First, in a browser, bring up the ewdMonitor application. e.g. assuming your EWD.js machine’s IP Address is 192.168.1.100:

http://192.168.1.100:8080/ewd/ewdMonitor/index.html

Now in your REST client, enter the URL:

http://192.168.1.100:8080/vista/initiate

You should get back a response similar to this:

{"Authorization": "88d707b4-34d2-447b-b91f-07037b1484fd"}

and you should see activity similar to this shown below in your EWD.js process log:

Request added to Queue: queue length = 1; requestNo = 120; after 0 days 0:17:03dispatching request to 5794 at 0 days 0:17:03child process 5794 received message:{ "type": "vista_rest", "action": "initiate", "params": { "headers": { "host": "192.168.1.188:8080", "connection": "keep-alive", "user-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36", "authorization": "4e827198-8026-47a4-aab8-92213e5722ff", "accept": "*/*", "accept-encoding": "gzip, deflate, sdch", "accept-language": "en-US,en;q=0.8", "cookie": "CacheBrowserId=9rUC5W1q5JWbP0YFIwQoLw--; state-666E1C02-315E-11E5-8917-0C29C5382300=SYSADM%3A0%2C0; Username=UnknownUser; CSPWSERVERID=hzYGhv9i" }, "method": "GET", "query": {} }}vista-rpc.runRPC: {"rpcName":"XUS SIGNON SETUP"}**** data = {"name":"XUS SIGNON SETUP"}child process returned response {"pid":5794,"type":"sendMsgToAppUsers","appName":"ewdMonitor","content":{"type":"newSession","json":{"sessid":"97","appName":"vista","expiry":"Mon, 25 Jan 2016 14:29:22 GMT"}},"processNo":0}***** status = OKchild process returned response {"content":{"Authorization":"88d707b4-34d2-447b-b91f-07037b1484fd"},"action":"initiate","type":"vista_rest","pid":5794,"release":true,"processNo":0}process 5794 returned to available pool; type=vista_rest

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �7

Page 8: RPCBroker.js Installation & Reference Guide

You can now confirm that the Mumps.VistA symbol table management worked OK:

a) In another terminal process, enter the interactive Mumps shellb) switch to the correct namespace for your VistA systemc) Using ewdMonitor, select the Sessions tab and find the new session for the “vista” application

that will have been started. Note its session Id (eg 96)d) In the Mumps/Cache shell type: w $$getSessionSymbolTable^ewdjsUtils(96) [change the

number to whatever the session Id is on your system]. This command swaps in the symbol table that was saved into the specified EWD.js Session.

e) now type w to list the symbol table. It should look something like this if everything worked:

VISTA>w $$getSessionSymbolTable^ewdjsUtils(96)okVISTA>w

DIC(0)=""DILOCKTM=3DISYS=18DT=3160125DTIME=300DUZ=0DUZ(0)="@"DUZ("LANG")=""I=15IO=""IO(0)=""IO("CLNM")=""IO("IP")=""IO("ZIO")=""IOBS=""IOF="#"IOM=""ION=""IOPAR=""IOS=0IOSL=""IOST=""IOST(0)=0IOUPAR=""POP=0U="^"XOPT="^5^600^1^1^1^^^Y^4000^0^^^N^9000^^500^1"XQVOL="ROU"XQXFLG("ZEBRA")=-1XUCI="VISTA"XUDEV=0XUENV="VISTA^ROU^ubuntu^ROU:CACHE"XUEOFF="U $I:("":"+S")"XUEON="U $I:("":"-S")"XUF=0XUFAC=0XUIOP=""XUOSVER="2015.2 "XUVOL="ROU^^500"XWBAPVER=""XWBSTATE("XUS XOPT")="^5^600^1^1^1^^^Y^4000^0^^^N^9000^^500^1"Y=5VISTA>

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �8

Page 9: RPCBroker.js Installation & Reference Guide

You can see that the correct symbol table environment has been saved for re-use by this session. Each subsequent RPC invocation will update the saved symbol table appropriately, and they will be executed within the correct Mumps symbol table environment, just as if they were running in a legacy, dedicated, stateful process.

Now try logging into VistA:

a) In the REST client, copy the value of the Authorization property that was returned as the response from your first /initiate REST request, e.g. 88d707b4-34d2-447b-b91f-07037b1484f

b) Set it as the value of a header named Authorization. This is used for authentication and will hook your request up to the EWD.js session that was created and initialised by the /initiate request. All subsequent REST requests MUST include this Authorization header,

c) Now send the following URL:

http://192.168.1.100:8080/vista/login?accessCode=xxxxxx&verifyCode=yyyyyyy

Replace xxxxx with a valid Access Code and yyyyy with a valid Verify Code

If everything worked properly and you entered a valid access code & verify code, you should see a success response that looks something like this:

{"displayName": "CHERYL""greeting": "Good afternoon CHERYL""lastSignon": " You last signed on today at 13:49""messages": [5]0: " You last signed on today at 13:49"1: "You have 311 new messages. (311 in the 'IN' basket)"2: ""3: "Enter '^NML' to read your new messages."4: "You've got PRIORITY mail!"-}

if you entered an invalid access/verify code, you’ll get an error like this (as you’d expect from the underlying XUS AV CODE which is what is being invoked by the /login request):

{"error": "Not a valid ACCESS CODE/VERIFY CODE pair."}

d) Now that you’re logged in, you can use the runRPC REST method. This will attempt to invoke the RPC you specify. The format depends on the complexity of the RPC’s inputs.

For simple RPCs with just one or more values of type LITERAL, you can use a GET request structured as follows:

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �9

Page 10: RPCBroker.js Installation & Reference Guide

http://192.168.1.100:8080/vista/runRPC/{RPC Name}?{type}={value}[&{type}={value}

where RPC Name is the name of the RPC you want to run You then define each type and value for the RPC

for example:

GET http://192.168.1.100:8080/vista/runRPC/XWB EGCHO STRING?literal=Hello World!

which should return a response:

{"type": "SINGLE VALUE""value": "Hello World!"}

For RPC with complex inputs (eg LISTs and/or combinations of different types), you should use a POST request and specify the inputs as a JSON object in the request’s data payload. You MUST specify the Content-Type to be application/json.

For example:

POST http://192.168.1.100:8080/vista/runRPC/DDR GETS ENTRY DATA

with a Content-Type = application/json

and data payload:

[ { "type": "LIST", "value": { "FILE": "200", "FIELDS": ".01", "IENS": ".5,", "FLAGS": "IE" } } ]

The payload must be proper JSON syntax: i.e. both property names and values double-quoted. Type values and value names can be mixed case: RPCBroker.js normalises them to upper-case before they are invoked within VistA itself.

Note:

a) In a raw REST client environment, you’ll need to URL-escape the spaces within RPC names with %20. Many REST clients will do this automatically for you. The examples here show the un-escaped RPC names for clarity.

b) The RPC context defaults to OR CPRS GUI CHART but you can over-ride this by setting an EWD.js session variable: session.$(‘VistA’).$(‘context’). You’ll need to do this via post-login processing and/or a custom REST URL (see later). This mechanism ensures that the context is set specifically for the individual user, and NOT globally for all RPCBroker.js users. Additionally, by being set at the back-end within the user’s EWD.js session, it cannot be altered or tampered with by the end user or REST client.

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �10

Page 11: RPCBroker.js Installation & Reference Guide

c) Similarly, the RPC division defaults to 500, but you can over-ride this by setting an EWD.js session variable: session.$(‘VistA’).$(‘division’).

c) RPCBroker.js EWD.js sessions will time out in 1 hour if there is no activity from the user. Timed out sessions are automatically garbage-collected by EWD.js. You can adjust this timeout by setting a new value (in seconds) for the EWD.js session variable named ewd_sessionTimeout, e.g:

session.$(‘ewd_sessionTimeout’)._value = 1200;

Custom RPC URLsYou’ll probably find that the runRPC request is too limiting for many situations. For example, you may want to do pre- or post- processing before/after an RPC call, customise and/or re-format the response that’s returned to the client and/or invoke multiple RPCs at the back-end from a single REST request.

RPCBroker.js makes this possible by allowing you to define your own custom RPC URLs. Essentially you define two things:

- the name and HTTP method of your RPC URL (eg patient and GET)- the back-end JavaScript logic that will be used to invoke your RPC(s) and perform pre- and/or

post- processing

You define your custom RPC URL handlers in a module file - its name is up to you, but must have a file extension of .js and must reside in the ~/ewdjs/node_modules directory

You then have to instruct EWD.js to automatically load it by adding the following into the startup file’s callback function:

ewd.customObj = { handlerExtensionModule: {nameOfYourModule} };

For example, if your custom RPC URL Handler module is named ‘myAddedHandlers,js’, your EWD.js start file’s start() function would look like this:

ewdjs.start(params, function() { ewd.customObj = { encryptAVCode: false, handlerExtensionModule: 'myAddedHandlers' }; require('ewd-vista-rest');});

So what would a custom RPC URL Handler module look like? Here’s a simple example: one that defines a new URL for ‘GET patient’ which, behind the scenes, invokes the ORWPT SELECT RPC:

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �11

Page 12: RPCBroker.js Installation & Reference Guide

var vistaRPC = require('ewd-vista-rpc');

var handler = { patient: { GET: function(ewd, session) { var args = { rpcName: 'ORWPT SELECT', rpcArgs: [{ type: 'LITERAL', value: ewd.query.patientId }], }; var response = vistaRPC.run(args, session, ewd); return { content: response, action: 'patient' }; } }};

module.exports = {handlers: handler};

Key details are as follows:

1) Your module should require the ewd-vista-rpc module2) It should define an object which is exported with the name ‘handlers’. In the example above,

it’s defining an object named “handler” which the module.exports command at the bottom exports.

3) the first-level property of the handler object defines the new URL path names. Here it defines a single new one named patient. The 2nd-level property defines the HTTP verb that it applies to: in this case GET. So we’re defining a handler for a GET request where the basic URL will be:

http://192.168.1.100:8080/vista/patient

4) Each handler function takes 2 arguments: ewd and session. ewd is the standard object passed by EWD.js to any back-end module, and session is a GlobalNode Object pointing to the current EWD.js session. Any name/value pairs that are added to the URL are accessed via ewd.query.name. So in the example above, the patient Id we’re selecting is accessed as ewd.query.patientId. The full URL would therefore be of the type:

http://192.168.1.100:8080/vista/patient?patientid=760

In this way, it’s up to your logic to define the syntax of your custom RPC URL. Through the ewd object you have access to:

- ewd.query: the URL’s name/value pairs - ewd.path: any sub-path within the URL that followed that action you’re handling (eg after / patient/ in the example above) - ewd.post_data: any data within the request’s body - ewd.headers: the HTTP request headers

5) In the example above I’m not doing any pre- or post- processing, but I could: through the ewd and session objects, you have access to everything in the user’s session and even the Mumps/VistA environment.

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �12

Page 13: RPCBroker.js Installation & Reference Guide

6) To invoke an RPC, you create an arguments object (here named args) which defines the RPC name and an array of input arguments for that RPC. Each input argument is an object that defines its type and value. You then invoke the run() function of the ewd-vista-rpc module.

7) Your handler function must return an object containing two properties: - content: a string or object containing the response payload that will be returned as the REST response - action: a string value which must be the same as the 1st-level function name (ie the URL path name) - in the case of the example above, that’s ‘patient’

In the example above, I’m just returning the raw response from the RPC, but I could have done post-processing to it and returned some other derived object from its contents.

8) Although the example above shows just a single RPC being invoked within the /patient handler, it could have invoked a sequence of them. Note that the vistaRPC.run() function executes synchronously. Each invocation of the run() function automatically restores the symbol table into the back-end Mumps process before it executes the RPC, and then saves the symbol table into the user’s EWD.js session afterwards.

9) It is possible to set / reset the RPC context from within a custom RPC URL handler function. Simply set the value in the following manner:

session.$(‘VistA’).$(‘context’)._value = ‘DVBA CAPRI GUI’;

Optional Post-Login ProcessingYou can optionally define a post-login function that will be automatically invoked immediately after a successful /login request. This can be a convenient and sensible time to over-ride the default RPC context and/or division that is applied to all subsequent incoming requests from the logged-in user.

To add post-login processing, you define a function that you include in your Custom RPC URL Handler extension module (as described in the previous section). Note that it’s possible and OK to create such a module that ONLY specifies a post-login function and doesn’t specify any custom RPC URL handlers.

Your post-login function takes two arguments: ewd and session (just like custom RPC URL handler functions), and it must be exported as the property named ‘postLogin’. For example:

function postLogin(ewd, session) { session.$('VistA').$('division')._value = 100;}

module.exports = { postLogin: postLogin};

The extension module must, of course, be declared in your EWD.js startup file as before:

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �13

Page 14: RPCBroker.js Installation & Reference Guide

ewdjs.start(params, function() { ewd.customObj = { encryptAVCode: false, handlerExtensionModule: ‘myAddedHandlers' }; require('ewd-vista-rest');});

If your extension module also included custom RPC URL handlers too, it might look like this:

var vistaRPC = require('ewd-vista-rpc');

var handler = { patient: { GET: function(ewd, session) { //invokeRPC('ORWPT SELECT?literal=' + patientId + '&format=raw') var args = { rpcName: 'ORWPT SELECT', rpcArgs: [{ type: 'LITERAL', value: ewd.query.patientId }], }; var response = vistaRPC.run(args, session, ewd); return { content: response, action: 'patient' }; } }};

function postLogin(ewd, session) { //session.$('VistA').$('division')._value = 100;}

module.exports = { handlers: handler, postLogin: postLogin};

Preventing Use of the runRPC REST RequestYou may decide that you don’t want to provide the freedom for a REST client to invoke whatever RPC it likes (even though you control the context and division, and the user must have logged in with a bona fide AVCode that determines the extent of their access). Instead, you may decide that once logged in, the only RPCBroker.js requests that a client can invoke are the custom ones that you have defined in your extension module.

RPCBroker.js makes this very straightforward. Simply add the runRPC property to the ewd.customObj in your EWD.js startup file, e.g.:

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �14

Page 15: RPCBroker.js Installation & Reference Guide

ewdjs.start(params, function() { ewd.customObj = { encryptAVCode: false, handlerExtensionModule: 'myAddedHandlers', runRPC: { REST: false } }; require('ewd-vista-rest');});

If this is set, any attempt to invoke a /runRPC request will return an error. Remember to restart EWD.js to activate this setting!

By default, this parameter, if not specified, is true.

RPCBroker.js clients must still invoke the standard /initiate and /login requests before they can begin invoking your custom RPC URLs.

RPCBroker.js Security over RESTRPCBroker.js implements a strict set of security rules to prevent arbitrary (mis)use of RPCs:

1) You must invoke an /initiate request followed by a /login request before you can invoke RPCs2) Each request following an /initiate request must include the Authorization token (returned by

the /initiate) in the HTTP request header. This token is rigorously checked to confirm: - that it was generated by an /initiate request - that the session to which it points exists and hasn’t timed out An error response is returned if the token is not recognised or its associated session is non- existent or has timed out.3) The standard VistA mechanisms that determine whether or not the access code used to login

has access to a requested RPC are applied automatically4) Each RPC will run within the same Mumps symbol table that would exist in a traditional stateful

process 5) Sensitive information such as the DUZ is not exposed publicly or made directly accessible from

the REST client. Only the opaque Authorization token is available to the REST client.6) It is not possible for the user or client to set or reset the RPC context. This can only be done

from within your back-end logic.

Although the examples in this document show the use of the http:// protocol for REST requests, in a production environment you should enable SSL/TLS in your EWD.js environment, and use the https:// protocol for your REST requests.

Adding Further Security to the Login RequestIn the example described earlier in this document, we showed how the /login request includes the accessCode and verifyCode name/value pairs, with their values unencrypted, in the clear and using a GET request. This technique is useful for testing RPCBroker.js, but you may decide that it adds an unacceptable level of insecurity to the REST interface for VistA.

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �15

Page 16: RPCBroker.js Installation & Reference Guide

You should first note that the POST method is supported for the /login request, and this is usually believed to be more secure than using a GET request when sending sensitive information.

Secondly, the example I used showing /login with unencrypted AV codes is only possible if, in your EWD.js startup script, you explicitly specify that AVCode encryption is to be suppressed by defining:

ewd.customObj.encryptAVCode = false

eg:

ewdjs.start(params, function() { ewd.customObj = { encryptAVCode: false, handlerExtensionModule: 'myAddedHandlers', }; require('ewd-vista-rest');});

The default value of this property is true, meaning that RPCBroker.js will normally expect you to encrypt the user’s access code and verify code before using the /login method. Therefore in its default mode, RPCBroker.js will reject any attempts to login using unencrypted login credentials.

You’ll find that if you omit the encryptAVCode property from your EWD.js startup file, or explicitly set it to true, then when you invoke an /initiate request, you’ll see two additional values (key and iv) being returned in the response, e.g.:

{ "Authorization": "3b2b6f4c-15e2-41bf-a427-a0ed55586a50" "key": "c9ea893f43824f85b6f18474375bfd3d" "iv": 6466921310639009}

These values - key and iv - provide a one-time key and initialisation vector with which you must encrypt the access code and verify code. The encryption that RPCBroker.js expects you to use is AES-256-CBC.

If your RPC REST client logic is being written in JavaScript, then you can make use of the avEncrypt() function that is exported by the ewd-vista-security module. If you’re using other languages such as PHP, .Net or Java, then you will have to use an appropriate equivalent encryption function: they are commonly available (I’ve tested the AES-256-CBC encryption / decryption logic used by RPCBroker.js using online tools).

If you’re using the provided JavaScript avEncrypt() function, it’s very easy:

var vistaSecurity = require(‘ewd-vista-security’);var encrypted = vistaSecurity.avEncrypt(accessCode, verifyCode, key, iv);

where key and iv are the values returned in the /initiate response.

if you’re using your own function, the key thing you need to do is to concatenate the access code and verify code together before encryption as here:

var text = 'accessCode:' + ac + ';verifyCode:' + vc;

ie the string to encrypt might look like this:

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �16

Page 17: RPCBroker.js Installation & Reference Guide

accessCode=my!code;verifyCode=my-verifyCode!

Having encrypted the access code and verify code, you now use it in the /login request as follows:

http://192.168.1.100:8080/vista/login?credentials={encrypted value}

eg:

http://192.168.1.100:8080/vista/login?credentials=kjhuhhho98hio898lkjwqdj

On receipt of this request, RPCBroker.js decrypts the credentials before using them as inputs to the standard XUS AV CODE RPC.

The details of the mechanism used is as follows:

1) When you invoke an /initiate request, RPCBroker.js creates a random value for both the key and iv fields. It saves them in the new EWD.js session that has been also been created by the /initiate request handler

2) It then returns the key and iv values in the /initiate response3) When the encrypted credentials are sent in the /login request, the Authorization header value is

used to connect RPCBroker.js to the EWD.js session that was created by the preceding /initiate request. RPCBroker.js can then look up the key and iv code and use them to decrypt the credentials and recover the access code and verify code.

4) RPCBroker.js then uses the XUS AV CODE RPC to attempt to log in5) If the login fails, for whatever reason, RPCBroker.js deletes the EWD.js session. The key and

iv code are therefore destroyed and cannot be re-used. An error message is returned as the /login response.

6) If the login is successful, RPCBroker.js deletes the key and iv values from the EWD.js session, so they cannot be re-used. The user is flagged as being logged in.

7) Once an EWD.js session is flagged as being logged in, the /login request can no longer be used against that session. To log in with a different access code and verify code, you must send a new /initiate request which will create a new EWD.js session.

A key feature of this mechanism is that the encryption key and iv values are NEVER re-used. They are generated as random strings and are strictly one-time use only.

Example ScriptThe ewd-vista-rest module includes an example script, showing how a sequence of RPCBroker.js REST calls can be constructed programmatically using Node.js / JavaScript.

You’ll find the script file here: ewd-vista-rest/examples/VistA-client.js

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �17

Page 18: RPCBroker.js Installation & Reference Guide

Using EWD.js WebSocket Messages

RPCBroker.js doesn’t just limit you to REST. RPCs are accessible via EWD.js web socket messages. You can either invoke RPCs directly from the browser using a runRPC message type, or you can create your own message types whose handlers invoke RPCs in the back-end module, allowing you to perform pre- and post- processing, customise the response from RPC(s) and/or execute multiple RPCs from within a single message handler function.

Setting up the EnvironmentIf you’ve already set up your EWD.js environment for use with RPCBroker.js REST calls then you’ve nothing further to do.

If you’ve not installed anything yet and just want to run EWD.js applications with RPCBroker.js, then all you need to do is:

npm install ewd-vista-rpc

Using RPCBroker.js with EWD.jsYou can invoke RPCs in one or other of two ways from within an EWD.js application:

- from within your application’s back-end message handler module- directly from the browser, using ewd-vista-rpc as a micro-service

The former approach is highly secure, allowing no direct intervention from the browser in terms of what RPCs can be invoked from within your application. The security implications of the latter need to be carefully considered.

Invoking RPCs from a Back-end Message Handler FunctionYour back-end module must load the ewd-vista-rpc module, e.g.:

var vistaRPC = require(‘ewd-vista-rpc’);

You must first log in to VistA by using the function:

var results = vistaRPC.onMessage.login(params, ewd)

where params is an object containing the access code (params,accesCode) and verify code (params,verifyCode) ewd is the standard EWD.js object that your message handler function is passed by EWD.js

If an error occurs during login (eg due to an invalid set of AV Codes), results will be an error message of the form:

{error: errorMessageText}

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �18

Page 19: RPCBroker.js Installation & Reference Guide

A successful login returns an object containing the standard results from the XUS AV CODE RPC:

- displayName- greeting- lastSignon- messages

It also automatically sets the ewd.session.isAuthenticated property to true.

Once logged in, it’s then a simple matter of invoking the function:

var results = vistaRPC.onMessage.runRPC(params, ewd)

where params is an object that defines the RPC name (rpcName) and inputs (rpcArgs), eg:

var params = { rpcName: 'XWB EGCHO STRING', rpcArgs: [{ type: 'LITERAL', value: 'This is a test!' }], }; return vistaRPC.onMessage.runRPC(params, ewd);

RPCBroker.js automatically checks the ewd.session.isAuthenticated property whenever this runRPC function is invoked. An error is returned if it isn’t set to true - i.e. RPCBroker.js will refuse access to RPCs unless the user has properly logged in using a valid set of AV codes.

Invoking RPCs directly from the BrowserIf you wish, you can configure your EWD.js application to use ewd-vista-rpc as a set of micro-services.

Your application’s back-end module must export the following in order to permit access to this service:

services: function() { return ['ewd-vista-rpc']; }

From the browser you can then invoke any RPC by sending a message with a type ‘runRPC’ and service ‘ewd-vista-rpc’. The message’s params property must define the RPC’s name (rpcName) and inputs (rpcArgs).

For example:

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �19

Page 20: RPCBroker.js Installation & Reference Guide

EWD.sockets.sendMessage({ type: 'runRPC', params: { rpcName: 'XWB EGCHO STRING', rpcArgs: [{ type: 'LITERAL', value: 'This is a test!' }], }, service: 'ewd-vista-rpc', done: function(messageObj) { if (messageObj.message.error) { alert(messageObj.message.error); } else { console.log(JSON.stringify(messageObj)); } } });

As you can see, this is otherwise a standard EWD.js message whose response can be handled in the normal ways. Note, however, that the full, raw response from the RPC will be sent to the browser. Other than for internal testing purposes, this may present too insecure an environment.

Note:

1) You can only login to VistA using the provided vistaRPC.onMessage.login() function. You can’t invoke its underlying RPC using the runRPC() function

2) Note that applications that do not permit the use of the ewd-vista-rpc micro-service are automatically unable to invoke RPCs directly from within the browser. So for maximum security, simply don’t enable access to this micro-service from within your application’s back-end module.

RPC Context and DivisionBy default, the RPC context is set to OR CPRS GUI CHART and the division set to 500. You can modify these at any time from within any of your back-end message handler functions by setting the values of the Session variables VistA.context and VistA.division, eg:

ewd.session.$(‘VistA’).$(‘context’)._value = ‘DVBA CAPRI GUI’;

ewd.session.$(‘VistA’).$(‘division’)._value = 100;

Try Out the Included ExampleYou’ll find the source code for a simple, working EWD.js application that demonstrates all these capabilities in the ewd-vista-rest repository. You’ll find it here:

/examples/ewdApp

Simply create a new application directory on your system:

~ewdjs/www/ewd/RPCBrokerTest

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �20

Page 21: RPCBroker.js Installation & Reference Guide

Copy the index.html and app.js files into this directory.

Then copy /examples/ewdApp/node_modules/RPCBrokerTest.js into your ~/ewdjs/node_modules directory.

Start the application:

http://192.168.1.100:8080/ewd/RPCBrokerTest/index.html

Login using a valid AV Code pair and you’ll see 2 buttons, one which invokes an RPC from the back-end, and the other directly from a web-socket message. You’ll be able to see the incoming responses if you open up your browser’s JavaScript console.

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �21

Page 22: RPCBroker.js Installation & Reference Guide

Support for RPCBroker.js

RPCBroker.js is provided free of charge as a set of Apache 2-licensed Open Source modules. As such, no warranty or support is included with RPCBroker.js.

However, as with EWD.js, you are encouraged to post any problems, solutions, suggestions, bug reports etc in the EWD Community Group:

https://groups.google.com/forum/#!forum/enterprise-web-developer-community

For higher service levels, customised support agreements can be negotiated. Contact Rob Tweed at [email protected].

Note: Please do NOT send technical questions regarding either EWD.js or RPCBroker.js directly by email to Rob.

© 2016 M/Gateway Developments Ltd RPCBroker.js Page �22