Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Exercises

Dennis Patterson edited this page Apr 13, 2020 · 22 revisions

Now that we know how to setup CDS Services in the discovery endpoint, and have seen how to add POST routes to our own CDS Services, you can try a few different exercises to either edit or add CDS Services.

Helpful reference: CDS Hooks Cheat Sheet

Note: While your localhost server is still running, any changes made to the Express app will update the server automatically, so you don't need to restart the server every time you want to update the Express application.

Warm-up Exercise - Browser Debugging and CORS

We’ll start with a few introductory steps to observe the effects of changing CORS configuration and touch on browser console debugging.

Use your browser’s JavaScript console to view any issues the public sandbox might have calling your services. (E.g. info for Chrome or Firefox)

Allowed Origins

  1. Update the CORS configuration to limit browser calls to https://www.google.com

    • Refresh the sandbox browser tab. What happens? What’s in the browser console?
    • Can you still access the discovery endpoint directly? (e.g. in a separate tab, curl, or Postman)?
  2. Update the CORS configuration to allow access from the sandbox origin.

    • Refresh the sandbox browser tab to verify your service's card is returned again

Refer back to the resources listed on Cross Origin Resource Sharing (CORS) if you need to confirm syntax.

Exercise - Customizing a Card with Prefetch Data

Include the birth date in the patient-view-example CDS Service response in the detail attribute of the card. See it render on the CDS Hooks Sandbox.

Hint: See how the detail attribute is included in a card here

Exercise - Returning an App Link Card

Add a SMART app link to the response of either CDS Service we have already created. You can add your own SMART app launch URL if you have one, or you can use this launch URL for the Cerner SMART on FHIR Tutorial App:

http://engineering.cerner.com/smart-on-fhir-tutorial/example-smart-app/launch.html

See the CDS Service Response section of the CDS Hooks documentation for a refresher on how to add links to cards.

Once you have modified the service response to include the SMART app links, try launching it in the sandbox.

Exercise - Create a New Service that Queries for Needed Data

Goal: Create another CDS Service in index.js for the patient-view hook that only returns a card with a warning indicator if the patient has a condition of hypertension with the specific SNOMED code, 1201005. The summary property of the card should display the specific condition the patient has.

To test this functionality, you can use the default patient for the sandbox.

Step 1 - Return Card for All Patients

To start, create a new service that returns a warning card for hypertension for any patient in context of the request. This allows you to ensure that the service is 1) discoverable and 2) establish your card design.

Step 2 - Construct FHIR Query

Capture the FHIR endpoint and default patient provided in the request and use a tool like curl or Postman to construct a working FHIR query to discover whether that patient has the SNOMED code mentioned above.

Hint: Use the Condition FHIR resource to grab conditions of the patient. Make sure to check that the system property in the code part of the Condition resource has the value of http://snomed.info/sct.

(Advanced) Step 3 - Return Card for Only Patients With Hypertension

Use a library (e.g. fhir.js, axios) to identify whether the patient in context has hypertension and only return the card if this holds true.

For testing, you can query for another patient without hypertension to verify that your logic discovers the condition successfully.

Exercise - Authorization

The goal of this exercise is to validate the Authorization header provided in a request and limit access to only trusted CDS Clients.

Step 1 - Manual Token Validation

To better understand token format and the steps required to validate, the first step will be to perform manual verification steps.

  1. Capture an example token being sent to your server during a hook invocation
  2. Navigate to jwt.io and paste the token in the Encoded section of the Debugger
    • In the Decoded section on the right hand side, note the 3 portions: Header, Payload, and Verify Signature
  3. Obtain the jku from the Header and open that in a new browser tab to view the JSON Web Key (JWK) Set.
    • While the public sandbox may only have one key, note the match between the kid in the JWT header and the kid in the key set. This lets you know that's the correct key to use for signature verification.
    • Copy the single key (not the whole keys array) to your clipboard.
  4. Navigate back to jwt.io and paste the key into the Public Key portion of the Verify Signature section. You should see Signature Verified underneath the text input where you entered the token.
    • Note that you can also verify the JWT by providing the public key in PEM format. Some token validation libraries require this, as well, so you may need to convert from JWK to PEM when you perform validation in your code.
  5. Now that we've verified the signature, take a moment to inspect the token payload and compare with what the specification outlines around token format.
    • Is the token issuer who you expect? Does the audience match your server endpoint? Are the issued-at-time and expiration times appropriate?

(Advanced) Step 2 - Token Validation Using Known Public Key

Now, let's start building out code to accomplish token validation

  1. Start requiring consumers to supply a token by commenting out the code to default a token.
  2. Store the known public key in a variable so we can use it to verify incoming tokens.
  3. Use jwt.io's list of libraries to identify a library to use. Use Filter By to limit to JavaScript or node.js.
    • Pay attention to how the library expects the public key to be provided. You may need to convert to pem format or use another class to process the key first.
    • Most libraries can help with validating the JWT payload in addition to the signature, so avail yourself of that functionality.

(Advanced) Step 3 - Dynamic Public Key Discovery

In this step, we want to move away from hardcoding a single public key and be able to be dynamic with our approach, allowing support for additional CDS Clients and realizing that they will be rotating their public keys.

  • Prior to JWT signature verification, use the JWT library to decode the token. Retrieve the JWK set.
  • Use the kid in the JWT header to identify the matching public key.
  • Use the mechanisms in your chosen library to verify the JWT signature using that key.

Next step: Next Steps