Security Walkthrough Information

Note that this page is specifically written as a step by step guide to using CWS. For technical information, see here.

Overview

CWS uses OpenSSL public/private key encryption for all webservices. This means that messages sent to CorEMR and responses sent back to clients can be verified by the reciever that it came from who it claims. To accomplish this goal, both parties will create and maintain their own private and public keys, which will then be used to "sign" a message body, which upon reciept can be verified to be a real signature.

For almost all actions in this regard, CorEMR recommends using OpenSSL. Other software may work, but all further documentation will keep OpenSSL in mind and refer to its commands. For OpenSSL installation help, follow the guides on their website or contact CorEMR support. CorEMR also recommends using Postman in order to create and send API requests. Any API software will work with CWS, but Postman is our preferred method and is our recommendation.

With this information in mind, see the corresponding sections below for walkthroughs on how to accomplish common goals.

Security Setup

CorEMR will handle most parts of security creation and initialization. However, clients will have to create their own public and private keys. This can be accomplished via OpenSSL using the following commands. Ensure they are ran in this order or they may not function correctly:

  1. openssl genrsa -out rsa.private 4096
  2. openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM

This will create two new files: rsa.private and rsa.public. Note that by using '4096' as the value in the command you are creating a longer than average key that will be more secure. This number can be decreased, but 4096 is CorEMR's recommended configuration. These two new files will be crucial moving forward, but the largest idea to take away is that clients are responsible not to lose their individual rsa.private key. If the private key is lost or an unknown third party gains access to it, inform CorEMR immediately. This could result in a data breach and quick removal of access to CWS is crucial to avoid it.

With all this in mind, we can open the rsa.public file (if your system doesn't know how to open either file, choose to open it with notepad) and copy all contents within it. We can then go into the CorEMR application, choose 'Administration', then 'Public Keys', and finally the plus sign in the bottom right hand corner. Paste the contents from the public key file into 'Contents' and choose a username that you will easily remember. This will be used often, so ensure it's something unique. With that, store the rsa.private file somewhere safe, and setup is complete.

Sending a Request

CorEMR Web Services requires every message body be signed by the sending party, even if that message body is empty. Therefore, when sending a request to hit any endpoint, follow these steps:

  1. Copy the body of your request into a file called body.txt (if the request is a GET request or the body is otherwise empty, create an empty file called body.txt).
  2. Using your securely stored rsa.private key, use the following command to sign the body of the request: openssl dgst -sha256 -sign rsa.private -out sign.sha256 body.txt
  3. This will generate a new file called sign.sha256 which will contain a signature in an unreadable format, use the following command to encrypt it into base64: openssl enc -A -base64 -in sign.sha256 -out sign.txt
  4. A new file will now exist called sign.txt. Open it and copy the contents exactly, this is your signature which CorEMR will use to verify the request as real. With this, go back into your request and add a new header called 'Authorization' with the following contents: CWS-SHA256 Access=USERNAME, Signature=BASE64_SIGNATURE Where USERNAME is replaced with the username of the public key within CorEMR's application that correlates to your private key, and BASE64_SIGNATURE is everything copied from sign.txt. Note here that we used CWS-SHA256 since that's the algorithm we used to sign the body. CWS-SHA1 is also supported but must also be used to sign the request back in step 2 via the -sha1 command.
  5. With the header and body now connected to each other via the signature, the request can be sent. If any mistakes are made along the way, CorEMR will reject the request and inform the user of the problem. Contact CorEMR Support if issues persist or with any questions.

Verifying CorEMR's Response

All CWS responses include a header called 'Authorization' with the following contents:

ALGORITHM Access=USERNAME, Signature=BASE64_SIGNATURE

Where ALGORITHM is typically replaced with either CWS-SHA256 or CWS-SHA1, USERNAME is replaced by a varient of coremr, and BASE64_SIGNATURE contains a human readable signature. Note that this will look very similar to the request header that was attached to your initial request. In order to verify that this reponse came from CorEMR, follow these steps:

  1. Create a new text file called response_sign.txt, copy and paste the exact value of BASE64_SIGNATURE into this without changing anything.
  2. Use the following command to decrypt the base64 signature into a machine readable format: openssl enc -d -A -base64 -in response_sign.txt -out response_sign.sha256 This will create a new file called response_sign.sha256 that we will use momentarily.
  3. Go into the CorEMR application and choose 'Administration' then 'Public Keys'. There should be a key with a username that perfectly matches USERNAME located in the header. This is CorEMR's public key, and you will use it to verify the signature. Copy all of the contents of this key and place it into a new file called rsa.public.
  4. Next, copy the exact data from the body of the response, ensure that it is the raw data that has not been formatted in any way. Paste this into another new file called body.txt
  5. Run the following command to verify that the body of the response was signed by CorEMR: openssl dgst -sha256 -verify rsa.public -signature response_sign.sha256 body.txt
  6. If the response returned is "Verified OK" and all above steps have been followed exactly, the response is verified to have come from CorEMR. If any other response is returned and no mistake was made during the process of verification, the response could be fradulant and CorEMR should be informed immediately.

Example Request

In this example, we will be creating a new patient request by hitting the /ws/patients/ endpoint. Our body will look something like this:

{
  "external_id": "FakeExternalID",
  "facility": 10000,
  "agency": 2,
  "billing_agency": 1, 
  "fname": "First",
  "lname": "Name",
  "dob": "2000-04-12 10:00:00.000",
  "sex": "M",
  "booking_no": "EthanBooking14",
  "booking_date": "2023-04-07 10:00:00.00"
}

Note that the body must be written in proper JSON format and that there could be more optional fields included here. Our header will contain a key called "Authorization" with a value that looks something like this:

CWS-SHA1 Access=fake-username, Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
XXxxxXXxXXxxXXxxXXXXXxXXXxXXxXXXXxxxxxXxxxXxXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxXXxXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxXXX==

Where the X's will be replaced with seemingly random uppercase and lowercase letters, slashes, and numbers. If this format is followed, the request should work.