FHIR data service for Include DCC and Kids First uses the Smile CDR FHIR server.
The current version of the FHIR servers is Smile CDR 2023.02.R02 (Wizard). See changelogs for details
Kids First FHIR services have been deployed into the DEV and QA environments within the Kids First Strides AWS account.
The FHIR endpoints for each of these environments are:
Include DCC FHIR services have been deployed into the DEV and QA environments within the Include DCC AWS account.
The FHIR endpoints for each of these environments are:
The old servers are still deployed and will be maintained until we fully transition to the new servers mentioned above. Documentation for the old servers can be found here: README.md
Key feature differences between the legacy servers and upgraded servers are:
Legacy | Upgraded | |
---|---|---|
OAuth2 Authentication | ❌ | ✅ |
Custom Authorization | ❌ | ✅ |
Swagger API docs | ❌ | ✅ |
Auditing | ❌ | ✅ |
Important Note: Although custom authorization and auditing is supported in the new FHIR servers, we have not yet implemented or enabled those features.
These FHIR services support OIDC based authentication using the OAuth2 Client Credentials Flow. We use the open source OIDC provider Keycloak.
In order to begin interacting with the server you will need to register a new client. Please email or slack one of the Keycloak admins:
Please include:
Once you've registered you will receive:
token_url: url to get tokens from
client_id: your client id
client_secret: your client secret
These client credentials can be used to get a token which will work for any of the KF/INCLUDE servers deployed in either DEV/QA.
Please keep the client secret securely and privately stored!
Any machine wanting to access the FHIR service must authenticate by providing a valid OAuth2 access token issued by the OIDC provider. Here we will walk through an example of how any request to the server will be made.
Let's pretend we have registered a client in the QA environment with the following credentials and then use these to get the access token from Keycloak:
client_id: myclient
client_secret: mysecret
token_url: https://keycloak-qa.kf-strides.org/realms/FHIR-TEST/protocol/openid-connect/token
curl -X POST -d "client_id=myclient&client_secret=mysecret&grant_type=client_credentials" \
-H "Content-Type: application/x-www-form-urlencoded" \
https://keycloak-qa.kf-strides.org/realms/FHIR-TEST/protocol/openid-connect/token
You will get something that looks like this:
{
"access_token": <long base64 encoded string removed for brevity>,
"expires_in": 3600,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0,
"scope": "email profile fhir"
}
Now you can use this token to authenticate with the FHIR server and make requests.
curl -X GET -H 'Content-Type: application/json' \
-H 'Authorization: Bearer <put access token here>'\
https://fhir-qa.kidsfirstdrc.org/Patient
Note that your code will need to include logic that requests a new token after the current token expires.
These example queries can be used to search for all of the Kids First FHIR resources.
NOTE These queries use the PRD legacy server because it does not require auth to view data and this makes it easiser to test out in a browser. You can use the same queries on the upgraded FHIR server but you must include the access token for authorization.
Query for study specific resources using _tag
query parameter. All resources
are tagged with the study ID
https://fhir.kidsfirstdrc.org/Patient?_tag=SD_MEOWME0W
Use the _total
query parameter to include total count of resources
https://fhir.kidsfirstdrc.org/Patient?_tag=SD_DYPMEHHF&_total=accurate
https://fhir.kidsfirstdrc.org/Patient?_tag=SD_DYPMEHHF
https://fhir.kidsfirstdrc.org/Patient?_tag=SD_DYPMEHHF
https://fhir.kidsfirstdrc.org/Group?_tag=SD_DYPMEHHF&code=FAMMEMB
https://fhir.kidsfirstdrc.org/Observation?_tag=SD_DYPMEHHF&code=FAMMEMB
https://fhir.kidsfirstdrc.org/Specimen?_tag=SD_DYPMEHHF
https://fhir.kidsfirstdrc.org/Condition?_tag=SD_DK0KRWK8&_profile:below=https://ncpi-fhir.github.io/ncpi-fhir-ig/StructureDefinition/phenotype
https://fhir.kidsfirstdrc.org/Condition?_tag=SD_DYPMEHHF&_profile:below=https://ncpi-fhir.github.io/ncpi-fhir-ig/StructureDefinition/disease
https://fhir.kidsfirstdrc.org/Observation?_tag=SD_DYPMEHHF&code=263493007
https://fhir.kidsfirstdrc.org/Observation?_tag=SD_DYPMEHHF&code=250537006
https://fhir.kidsfirstdrc.org/DocumentationReference?_tag=SD_DYPMEHHF
The quickstart script bootstraps the development environment, seeds the FHIR server with data, and sets up Keycloak with clients that have been assigned FHIR permissions. Run this script if you want to get up and running quickly and see how everything works.
Please make sure you have Docker installed on your system and it is running.
You will also need to do the following in order to access the private docker image on Github packages registry:
read:packages
scopeGITHUB_PAT_SMILECDR=<your token>
GITHUB_USERNAME=<your github username>
git clone git@github.com:kids-first/kf-api-fhir-service.git
cd kf-api-fhir-service
./src/bin/quickstart.sh --delete-volumes
If everything ran correctly, you should see this in your shell:
✅ --- Quickstart setup complete! ---
Let's try getting an access token from Keycloak for the ingest-study-client
client.
curl -X POST -H 'Content-Type: application/json' \
-d '{"client_id": "ingest-study-client","client_secret": "lkhZRex5E58JCjcnIKkLcT4t1Q9dw5OW"}' \
http://localhost:8081/token
You should get back a response that looks like this (access token removed for brevity):
{
"access_token": <access_token>,
"decoded_token": {
"acr": "1",
"allowed-origins": [
"/*"
],
"azp": "ingest-study-client",
"clientAddress": "192.168.176.4",
"clientHost": "192.168.176.4",
"clientId": "ingest-study-client",
"email_verified": false,
"exp": 1681241247,
"fhir_roles": [
"fhir-permission|role-fhir-client-superuser"
],
"iat": 1681237647,
"iss": "http://keycloak:8080/realms/fhir-dev",
"jti": "40b44b13-9b07-45c1-9432-ee1c17ebdab2",
"preferred_username": "service-account-ingest-study-client",
"scope": "fhir profile email",
"sub": "7a25c1e2-5403-476b-ab13-00acc1693a75",
"typ": "Bearer"
},
"expires_in": 3600,
"not-before-policy": 0,
"refresh_expires_in": 0,
"scope": "fhir profile email",
"token_type": "Bearer"
}
The actual base64 encoded access token needed to send requests to the
FHIR server will be in access_token
but you can see the decoded version of
it in decoded_token
. In the decoded version you can see the FHIR permissions
this client has.
Let's use the access token to view the FHIR data we are now authorized to see:
curl -X GET -H 'Content-Type: application/json' \
-H 'Authorization: Bearer <put access token here>'\
http://localhost:8000/Patient
You should get back the Patients that were added by the quickstart script.
If you find issues with Smile CDR itself, talk to a repo admin and/or ask for credentials to the Smile CDR support website. The engineers there are very responsive and helpful.
Smile CDR periodically releases new versions in the form of tarballs or docker images. Talk to a repo admin and/or ask for the CHOP credentials to access the releases website to download new images:
https://releases.smilecdr.com/
Run the following scripts to do steps 2-4. Here is an example of how to upgrade to version 2023.05.R02:
# Step 2
./bin/upgrade/new_image.sh ~/Downloads/smilecdr-2023.05.R02-docker.tar.gz 2023.05.R02
# Step 3
./bin/upgrade/upgrade_ghcr_image.sh kids-first:smilecdr/2023.05.R02
# Step 4
./bin/upgrade/upgrade_ecr_image.sh kf-strides-smile-cdr 2023.05.R02
All server settings are located in smilecdr/settings
smilecdr
`-- settings
|-- auth.js
|-- master.properties
|-- oidc-servers.json
|-- jvmargs.sh
|-- system-users.json
`-- users.json
The post authentication callback function that Smile CDR calls once the user has been authenticated. This function is responsible for extracting FHIR roles and permissions from the access token (in the case of OIDC) or user object (in the case of basic auth) and adding it to the user session.
See https://smilecdr.com/docs/security/callback_scripts.html#method-onauthenticatesuccess
This is the main configuration file for the server.
See https://smilecdr.com/docs/configuration_categories for details on each property.
A list of configuration objects for each OIDC server that you want Smile CDR to be aware of. Local Keycloak configuration is included.
See https://smilecdr.com/docs/configuration_categories for details on each property.
keycloak
`-- settings
|-- fhir-dev-realm.json
|-- fhir-dev-users-0.json
You may notice the instructions to get the access token are different here in the Developer section than the Quickstart secion.
Unfortunately we cannot send requests directly to Keycloak to get access tokens
since Keycloak will then use "localhost" in the access token's issuer field
(ex. http://localhost:8080/realms/fhir-dev/protocol/openid-connect/token
).
Then when this access token is sent to Smile CDR inside the docker stack, it
will fail since Smile CDR inside the docker network does not know what
http://localhost:8080
is.
To mitigate this we simply send requests to the proxy service which then forwards the request to the Keycloack docker service.
bin
|-- generate_data.py
|-- health-check.sh
|-- load_data.py
|-- quickstart.sh
|-- seed_users.py
`-- setup_dev_env.sh
One stop script to get the entire dev environment up with all sample data and users loaded into Smile CDR
Calls setup_dev_env.sh
There are two types of tests:
Integration tests are run against the full service suite including the FHIR server, the database, and the OIDC server. They test all CRUD functionality as well as authentication functionality.
These tests are written in Python and executed via the pytest framework. You can run the tests like this:
# Do this if you do not already have your services up.
./src/bin/quickstart.sh
# Do this once to install test dependencies
pip install -r dev-requirements.txt
# Run the integration tests
pytest tests/python
Unit tests do not require the services to be up as they test individual
functions in the src code. There are currently only unit tests to test the
Smile CDR authentication module in smilecdr/settings/auth.js
These unit tests are written in JavaScript and executed with the Jest framework.
You can run the unit tests like this:
# Do this once to install dependencies
npm install --prefix ./tests/javascript
# Run tests
./bin/run_js_tests.sh