In this tutorial, we'll configure Smile CDR to comply with the CMS-0057-F Consent Requirements for Provider Access.
We'll create two patients "Ollie Open" and "Patty Private" and four providers "Dr. Goody", "Dr. Nicey", "Dr. Baddy", and "Dr. Evil".
Ollie Open has no Consent resources.
Patty Private has four Consent resources:
Here are the outcomes we expect from this configuration:
Patient | Provider | Organization | Consent Outcome |
---|---|---|---|
Ollie | any | any | Allowed |
Patty | Dr. Nicey | Good Org | Allowed |
Patty | Dr. Baddy | Bad Org | Denied |
Patty | Dr. Goody | Bad Org | Allowed |
Patty | Dr. Evil | Good Org | Denied |
1. Install Smile CDR
Install Smile CDR either from a tarball or using Docker.
2. Build and Install the Demo Consent Interceptor
Download and unzip the cdr-consent-demoproject using one of the links below.
Now build the project and install the interceptor jar file in your smilecdr/customerlib directory.
cd cdr-consent-demoproject
mvn clean install
target/cdr-consent-demoproject-*.jar path/to/smilecdr/customerlib
3. Enable Consent Logging
Edit smilecdr/customerlib/logback-smile-custom.xml
and uncomment the last line to enable consent logging.
<!-- Consent Troubleshooting Log -->
<logger name="ca.cdr.log.consent_troubleshooting" level="DEBUG"/>
This will help us see how consent is being evaluated.
4. Start Smile CDR
Start Smile CDR by running the following command:
$ bin/smilecdr run
5. Access the Web Admin Console
Access the Web Admin Console by navigating to the following URL in your web browser:
http://localhost:9100
Log in with the default credentials "admin", "password".
6. Install an OpenID Connect Client
Save the following JSON to a file called oidc-client.json
:
{
"nodeId" : "Master",
"moduleId" : "smart_auth",
"clientId" : "consentdemo",
"clientName" : "Consent Demo",
"enabled" : true,
"accessTokenValiditySeconds" : 3600,
"allowedGrantTypes" : [ "AUTHORIZATION_CODE", "IMPLICIT", "REFRESH_TOKEN", "CLIENT_CREDENTIALS", "PASSWORD", "JWT_BEARER" ],
"alwaysRequireApproval" : false,
"attestationAccepted" : true,
"canIntrospectAnyTokens" : false,
"canIntrospectOwnTokens" : false,
"canReissueTokens" : true,
"clientSecrets" : [ ],
"createdByAppSphere" : false,
"fixedScope" : false,
"jwksUrl" : "",
"publicJwks" : "",
"refreshTokenValiditySeconds" : 86400,
"registeredRedirectUris" : [ "http://localhost:3000/callback", "http://localhost:3001/callback" ],
"rememberApprovedScopes" : false,
"scopes" : [ "online_access", "openid", "patient/*.read", "patient/*.write", "cdr_fhir_delete" ],
"secretClientCanChange" : false,
"secretRequired" : false
}
Navigate to Users & Authorization
OpenID Connect Clients
.
Click Choose File
and select the oidc-client.json
file you created.
Click Import
.
7. Give the ANONYMOUS user FHIR_CAPABILITIES permissions
Navigate to Users & Authorization
User Management
.
Beside the ANONYMOUS
user, click on Edit
.
Search for the FHIR_CAPABILITIES
permission and enable it.
Click Save User
.
8. Create 3 demo Users
We will create 3 users to test the consent module.
Navigate to Users & Authorization
User Management
.
Click Add User
.
Create users with the following details:
Username | Family Name | Given Name | Password | Location Launch Context | Practitioner Launch Context |
---|---|---|---|---|---|
drgoody | Goody | Dr | Password123 | Organization/bad-org | Practitioner/dr-goody |
drnicey | Nicey | Dr | Password123 | Organization/good-org | Practitioner/dr-nicey |
drevil | Evil | Dr | Password123 | Organization/good-org | Practitioner/dr-evil |
drbaddy | Baddy | Dr | Password123 | Organization/bad-org | Practitioner/dr-baddy |
Give all three users both ROLE_FHIR_CLIENT
and FHIR_ALL_READ
permissions.
Note in a real system, the launch context would be set by the IDP (Identity Provider). But to simplify things for this demo, we'll set the launch context directly on the user.
9. Add a Consent Module
Navigate to Configuration
Module Config
.
Select Consent
from the dropdown menu and click Add
.
In the FHIR Interceptors
section, set Interceptor Bean Types
to com.smilecdr.consent.DemoHooks
. This is the name of the class that we built and installed in step 2 above.
In the Consent
section, set Bucket Definition (Text)
to the following:
{
"canSeeResource": {
"consentServiceFactory": "smileDefaultConsentServiceR4",
"consentRules": [
{ "name": "PRACTITIONER", "matching": [ { "matchUrl": "Consent?category=INFA" } ]},
{ "name": "ORGANIZATION", "matching": [ { "matchUrl": "Consent?category=IDSCL" } ] },
{ "name": "ALL", "matching": [ { "matchUrl": "Consent?category=59284-0" } ] }
],
"fallbackConsentRule": "AUTHORIZED"
}
}
This demo uses 3 types of Consent resource categories to manage the 3 different levels of consent: all, organization, practitioner. For the demo, we arbitrarily chose 3 category codes from the list of R4 Consent Category Codes so to distinguish between these three kinds of Consent resources. Your system may choose a different approach to differentiate between these different kinds of Consent resources. Note the order of these rules is important, since ORGANIZATION consent needs to override ALL consent, and PRACTITIONER consent needs to override ORGANIZATION consent.
In the Dependencies
section, set FHIR Storage Module (any FHIR version)
to persistence (FHIR Storage (R4 RDBMS))
.
Click Create Module
.
Click Start
to start the Consent Module.
10. Enable OIDC Authentication and Consent on the FHIR Endpoint
Navigate to Configuration
Module Config
.
Click on fhir_endpont
on the left-hand side.
In the Auth: OpenID Connect
section, enable OpenID Connect Security
.
In the Dependencies
section at the bottom:
The Consent Module
dependency to consent (Consent)
.OpenID Connect Authentication
dependency to smart_auth (SMART Outbound Security)
.Click Save Config
.
Click Restart
to restart the FHIR Endpoint.
11. Enable New Session for Each Flow and CORS on the SMART Outbound Security Endpoint
Navigate to Configuration
Module Config
.
Click on smart_auth
on the left-hand side.
In the OpenID Connect (OIDD) section
, enable New Session for Each Flow
.
In the Cross-Origin Resource Sharing (CORS)
section, enable CORS Enabled
.
Click Save Config
.
Click Restart
to restart the SMART Outbound Security Endpoint.
12. Load the test data
Using a REST client such as Bruno or Postman, POST a transaction to the FHIR Endpoint. Use Basic Auth with credentials
'admin', 'password'.
http://localhost:8000/
Use this Consent Test Bundle as the body of the POST.
It should return a 200 OK HTTP response code with a copy of the Bundle you posted.
This bundle contains the following resources:
**13. Try accessing data without any Consent resources **
This demo ships with two applications: a Patient View app and a Consent Management app both located in the zip file you downloaded in the folder src/main/frontend
.
Start the Patient View app.
cd cdr-consent-demoproject-*/src/main/frontend/patient-viewer-demo
npm install
npm run dev
It should return with a message that includes something like the following:
- Local: http://localhost:3001
✓ Starting...
✓ Ready in 718ms
Navigate to the Patient View application at http://localhost:3001
.
Click Login with SMART
Use "drevil" "Password123" as the credentials. If you run into a problem at this point, see "Troubleshooting" below.
pat
and click Search Patients
.Patty Private
.Logout
.Now we know what it looks like when Dr Evil can see Patty's data, let's add some Consent resources to block that access.
14. Create some Consent Resources
Start the Consent Management app.
cd cdr-consent-demoproject-*/src/main/frontend/consent-management-demo
npm install
npm run dev
It should return with a message that includes something like the following:
- Local: http://localhost:3000
✓ Starting...
✓ Ready in 718ms
Navigate to the Consent Demo application at http://localhost:3000
.
Click Login with SMART
Use "admin" "password" as the credentials.
Click Authorize
to allow the Consent Demo application to access data on the FHIR Endpoint.
We will now create the 4 consent resources for Patty Private described at the beginning of this tutorial.
Type patty
in the search box and click Search Patients
.
Click on Patty Private
.
Deny All Access
and click Create Consent
. This will create a consent that denis access to all of Patty Private's data.Organization-specific
and select Good Org
from the dropdown. This will create a consent to permit Good Org to access Patty Private's data.Practitioner-specific
and select Dr. Goody
from the dropdown. This will create a consent to permit Dr. Goody's access to Patty Private's data.Practitioner-specific
and select Dr. Evil
from the dropdown. This will create a consent to permit Dr. Evil access to Patty Private's data.Edit
beside Dr. Evil's Practitioner-specific consent and change the Access Type
to Deny Access
.You should now see 4 Consent resources displayed for Patty Private.
Click Logout
.
Shut down the Consent Management app. (Ctrl-C)
**15. Try accessing data with Consent resources **
Start the Patient View app.
cd cdr-consent-demoproject-*/src/main/frontend/patient-viewer-demo
npm run dev
Navigate to the Patient View application at http://localhost:3001
.
Click Login with SMART
Use "drevil" "Password123" as the credentials.
pat
and click Search Patients
.Patty Private
.Click Logout
.
Click Login with SMART
Use "drgoody" "Password123" as the credentials.
pat
and click Search Patients
.Patty Private
.Try the other combinations of Patient and Provider to see the different outcomes.
16. Troubleshooting
The most likely root cause of a login problem is that you missed a step in the FHIR Endpoint or SMART Outbound Security Endpoint configuration above. Double-check those configurations first.
You can enable security troubleshooting logging on the server as follows:
customerlib/logback-smile-custom.xml
<!-- Security Troubleshooting Log : Authentication and Authorization -->
<logger name="ca.cdr.log.security_troubleshooting" level="DEBUG"/>