jupyterhealth / jupyter-health-software

A repository to track issues for the JupyterHealth Software Team
0 stars 0 forks source link

Documentation for the MVP for September 2024 - NOTE this is a WIP so check back for updates. #18

Closed surfdoc closed 1 week ago

surfdoc commented 1 week ago

RFC 2024-05-08 CHCS Identity & Access Management

Background

CommonHealth-CloudStorage (CHCS) is a web app built with Django that is used to share a patient's medical device data with researchers via the Common Health Android app. The established CHCS was required to support deployment to third-party servers without compromising data privacy and security. This was achieved by extensive use of cryptography and proxy design patterns, as outlined in this Google doc.

Problem

The cryptographic requirements for researchers to access and integrate with CHCS are impeding adoption.

Proposal

Drop the requirement to host CHCS on third-party servers and therefore the dependency on cryptography and instead support standards for authentication, authorization and integration.

The new implementation will support the following use cases for researcher end-users:

  1. Researcher access:

    1. Researcher signs-up and signs-in from web browser or SMART on FHIR EHR launch.
    2. (Not displayed in diagram) Researcher sets up organization hierarchies for institution, department, etc.
  2. Researcher creates study groups and invites colleagues to study groups.

  3. Researcher searches for existing patients or registers new patients. If SMART on FHIR launch, patient details are pulled from the EHR context.

  4. Researcher invites selected patients to selected study group (pending consent).

  5. Deep Link is sent by SMS or E-mail to patients.

  6. Patients launch deep link via Common Health Android app and give explicit consent for their specific medical device data to be shared with a specific study group.

  7. The Common Health Android app periodically downloads vendor medical device data to the patient's phone.

  8. The Common Health Android app periodically uploads medical device data to CHCS.

  9. Researcher views, sorts and downloads patient device data for the specific study.

  10. A REST API with OAuth2 for programmatic access

Technical Design

Authentication and Authorization

Direct Browser Access

E-mail/password sign-up and sign-in will be supported using the conventional django-oauth-toolkit using OIDC and OAuth2.

EHR Launch

A separate URI will be set up for EHR SMART on FHIR launches and the application will map the user's FHIR ID in users.identifier (see ERD below). The token checks in django-oauth-toolkit will need to be extended to switch for verification of tokens using the EHR keys for SMART launches (eg see Epic docs). The EHR launch may include contextual information such as the Patient ID that can be used by CHCS to shortcut to the corresponding patient screen.

Access Control

A user may choose to consent/share only a specific subset of scopes (eg Heart Rate) from a specific subset of device data (eg iHealth) with a specific study group. This fine-grained access control requires joining study groups (organizations) and device data (observations) with a reference to scopes.

The original requirements envisioned this IAM web app to be only concerned with authentication and authorization and retain the existing CHCS for data management. However to support the required fine-grained access control, the IAM web app needs to maintain a database with references to the complete catalog of data (or at minimum proxies for all data records). To achieve this with two different databases requires a syncing process to keep both databases up to date which adds significant complexity. It is therefore proposed to consolidate the IAM app and database with the CHCS app and database.

SMART Scopes

SMART v2 supports scopes to include search parameters, so in addition to scoping by resource (eg Observation) codes (eg Heart Rate) can be used to filter from the database and restrict access accordingly, eg

patient/Observation.r?code=http://purl.bioontology.org/ontology/SNOMEDCT/78564009
(Read Heart Rate)

A code parameter will be used to map SMART scopes to the corresponding Open mHealth SNOMED scope eg OMHealthResource.HeartRate.Read

Extensibility Considerations

Deep Link launches from Web Browsers

Data Model

Open mHealth

Device data is expected to be in the Open mHealth (JSON) format however the system can be easily extended to support binary data attachments or individual observation records. Binary JSON database fields (such as jsonb in Postgres) allow the structured JSON data to be queried from SQL.

FHIR

Tables and columns use a subset of the FHIR standard as a guide to support future extensibility and integration compatibility, for example the column user.name_family maps to the FHIR Person.name.family . The FHIR Observation supports a value.valueAttachment field to attach binary data, in this case binary JSON data in Open mHealth format. The FHIR CodeableConcept is used for scopes to reference the Open mHealth SNOMED code, eg 78564009 for Heart Rate.

erDiagram
    "users (FHIR Person)" ||--|{ "user_organizations": ""
    "users (FHIR Person)" ||--|{ "study_group_members": ""
    "users (FHIR Person)" {
        int id
        string identifier
        string password
        string name_family
        string name_given
        string telecom_email
    }
    "organizations (FHIR Organization)" ||--|{ "organizations (FHIR Organization)": ""
    "organizations (FHIR Organization)" ||--|{ "user_organizations": ""
    "organizations (FHIR Organization)" ||--|{ "smart_client_configs": ""
    "organizations (FHIR Organization)" ||--|{ "study_groups (FHIR Group)": ""
    "organizations (FHIR Organization)" {
        int id
        string name
        enum type
        int part_of
    }
    "smart_client_configs" {
        int id
        int organization_id
        string well_known_uri
        string client_id
        string scopes
    }
    "user_organizations" {
        int id
        int practitioner_id
        int organization_id
    }
    "patients (FHIR Patient)" ||--|{ "observations (FHIR Observation)": ""
    "patients (FHIR Patient)" ||--|{ "study_group_members": ""
    "patients (FHIR Patient)" {
        int id
        string identifier
        string name_family
        string name_given
        date   birth_date
        string telecom_email
        string telecom_cell
    }
    "study_groups (FHIR Group)" ||--|{ "study_group_members": ""
    "study_groups (FHIR Group)" ||--|{ "study_group_observation_consents": ""
    "study_groups (FHIR Group)" {
        int id
        int organization_id
        string name
        string description
    }
    "study_group_members" {
        int id
        int study_group_id
        int patient_id
        int user_id
    }

    "observations (FHIR Observation)" ||--|{ "study_group_observation_consents": ""
    "observations (FHIR Observation)" ||--|| "codeable_concepts (FHIR CodeableConcept)": ""
    "observations (FHIR Observation)" {
        int id
        int subject
        int code
        jsonb value_value_attachment_data
    }
    "codeable_concepts (FHIR CodeableConcept)" {
        int id
        string coding_system
        string coding_code
        string text
    }
    "study_group_observation_consents" ||--|| "codeable_concepts (FHIR CodeableConcept)": ""
    "study_group_observation_consents" {
        int id
        enum scope_action
        int scope_code_id
        int study_group_id
        int observation_id
        bool consented
    }

Users (FHIR Person)

Organizations (FHIR Organization)

SMART Client Configs

Study Groups (FHIR Group)

Observations (FHIR Observation)

CodeableConcepts (FHIR CodeableConcept)

Integration with CommonHealth Android App

Tech Stack

Capability Statement

OIDC/OAuth2+SMART Scopes Flow

sequenceDiagram
    actor Researcher Rachel
    participant CHCS-IAM Web App
    participant Patient Peter CH App
    Researcher Rachel->>Researcher Rachel: Recruits Patient Peter<br/>off-platform
    Note right of Researcher Rachel: peter@example.com<br/>+1 347-111-1111
    Researcher Rachel->>CHCS-IAM Web App: Signs-up/Signs-in via<br/>browser OAuth2
    Researcher Rachel->>CHCS-IAM Web App: Registers Patient Peter,<br/>enters Email, Cell
    Researcher Rachel->>CHCS-IAM Web App: Requests Deep Link
    Note right of CHCS-IAM Web App: Deeplink is standard<br/>OAuth2 presigned URL<br/>mapped to patient.id in DB
    CHCS-IAM Web App->>Researcher Rachel: Returns Deep Link<br/>as text
    Researcher Rachel->>Researcher Rachel: Sends Deep Link to<br/>Patient Peter off-platform
    Patient Peter CH App->>CHCS-IAM Web App: Launches Deep Link,<br/>Displays CHCS Scope<br/>Consent Requests 
    CHCS-IAM Web App->>Patient Peter CH App: Access Token<br/>& Refresh Token
    Note right of Patient Peter CH App: Token contain user.id<br/>and consented scopes
    Patient Peter CH App->>Patient Peter CH App: Vendor Sign-in and Sharing Consent
    Patient Peter CH App->>Patient Peter CH App: Periodic Vendor Data Download
    Patient Peter CH App->>CHCS-IAM Web App: Uploads Data with<br/>OAuth2 Access Token
    Researcher Rachel->>CHCS-IAM Web App: Views/sorts/downloads<br/>Patient Peter data 

SMART Client Flow

sequenceDiagram
    actor Dr Debora
    participant EHR
    participant SMART CHCS
    Dr Debora->>EHR: Seaches Patient Peter<br/>Clicks to launch CH
    EHR->>SMART CHCS: GET chcs.org/launch<br/>?iss=https://fhir.example.com&launch=xyz123
    SMART CHCS->>EHR: GET fhir.ehr.com/.well-known/smart-configuration
    EHR->>SMART CHCS: Conformance JSON<br/>grant_types_supported, authorization_endpoint,<br/>jwks_uri, token_endpoint, capabilities,<br/>code_challenge_methods_supported
    SMART CHCS->>EHR: GET auth.ehr.com<br/>?client_id=abc123&launch=xyz123<br/>&state=999&scope=launch+patient<br/>&redirect_uri=https://chcs.org/redirect&...
    EHR->>SMART CHCS: GET chcs.org/redirect<br/>?code=1111&state=999
    SMART CHCS->>EHR: POST<br/>code=1111, grant_type=access_token,scope=launch+patient,<br/>code_verifier=0f01, redirect_uri=https://chcs.org/redirect
    EHR->>SMART CHCS: Auth JSON<br/>access_token, token_type, scope, patient=def123.456
    SMART CHCS->>EHR: GET /fhir/patients/def.456<br/>Bearer: access_token
    SMART CHCS->>SMART CHCS: Matches EHR user.id<br/>to CHCS user
    EHR->>SMART CHCS: First Name, Last Name, Cell, E-mail
    SMART CHCS->>SMART CHCS: Matches EHR patient.id<br/>to CHCS patient
    SMART CHCS->>SMART CHCS: (Continues flow with Patient Peter<br/>SMART CHCS as above)
    SMART CHCS->>Dr Debora: Dr Debora signed in<br/>Patient Peter shared device data displayed

Reference Material

Established System

Information on the established system can be found at the following resources:

Established Flow

%% If this diagram is not rendered view at the following URL:
%% https://www.mermaidchart.com/raw/62c375bf-7445-489a-ab47-ed3e3cd6d2b3?theme=light&version=v0.1&format=svg
sequenceDiagram
    participant Partner
    participant Mobile Device
    participant CH App
    participant CHCS
    participant Vendor Service
    Partner->>CHCS: 1. Register Signing Keys and Branding Assets
    Note right of CHCS: Tables:<br/>users_cloudsharingpartner<br/>users_partnersigningkey
    Partner->>Partner: 2. Create new DeepLink (partner)
    Partner->>Mobile Device: 3. Send DeepLink (SMS, E-mail)
opt
    Mobile Device-->>Mobile Device: 4. Download CH App
end
    Mobile Device->>CH App: 5. Launch CH App with DeepLink
    CH App->>CHCS: 6. Verify DeepLink
    CHCS->>CH App: True/False
    CH App->>CH App: 7. User Consent
    CH App->>Vendor Service: 8. Vendor Sign-in and Sharing Consent
    Vendor Service->>CH App: 9. Periodic Vendor Data Download
    CH App->>CH App: 10. Create Local Data Group
    CH App->>CHCS: 11. Create User from Deep Link
    Note right of CHCS: Tables:<br/>users_cloudstorageuser
    CHCS->>CH App: Access Token
    CH App->>CHCS: 12. Sync<br/>Data Groups (client_data_grp_id, pub_encrypted_key_mtrl)<br/>Consents (client_data_grp_id, auth_req_jwt)<br/>Records (client_recrd_id, encrypted_content)<br/>Proxies (client_data_grp_id, client_recrd_id, encrypted_dek)
    Note right of CHCS: Tables:<br/>records_datagroup<br/>users_partnersharingconsent<br/>records_encryptedrecord<br/>records_dataproxyforrecord
    Partner->>CHCS: 13. Request Data (partner_id, partner_user_id)
    Note right of CHCS: Tables:<br/>records_encryptedrecord<br/>records_dataproxyforrecord
    CHCS->>Partner: Decrypted Records

Related Software

Name Description Language Features +/- Notes
pyoidc Minimal OIDC + OAuth2 implementation Python -SMART, +SAML Examples and docs unmaintained
oauthlib Minimal OAuth2 + OIDC Python -SMART, +SAML Guide to implement OIDC, see django-oauth-toolkit below
django-oidc-provider Minimal OIDC + OAuth2 implementation Python -SMART, -SAML uses Scope values, cannot request individual Claim
django-oauth-toolkit OAuth2 + OIDC, Built on oauthlib (see above) Python -SMART, -SAML Django standard, 3K stars
keycloak-extensions-for-fhir Extension for complete Auth Server Java +SMART, +SAML, +GUI Mature, 20K stars
supertokens Modern auth service Java -OAuth2, Does not yet support OAuth2
openemr Legacy EMR PHP +SMART, +FHIR, -SAML Poor docs and low quality codebase
medplum Modern CDR / EMR platform TypeScript +SMART, +FHIR, -SAML Comprehensive docs and examples. High quality codebase

Considerations

CHCS as a SMART Server

sequenceDiagram
    actor Dr Debora
    participant SMART CHCS
    participant Provider Directory Service
    participant Secondary App (SMART Client)
    Dr Debora->>SMART CHCS: chcs.org<br/>Sign up / Sign in
    opt
        SMART CHCS->>Provider Directory Service: SAML/SSO Auth
        Provider Directory Service->>SMART CHCS: 
    end
    Dr Debora->>SMART CHCS: Set up study, users and groups
    Dr Debora->>SMART CHCS: Register Patient, create and send deep link
    Dr Debora->>Secondary App (SMART Client): Click to launch
    Secondary App (SMART Client)->>SMART CHCS: SMART Auth flow
    SMART CHCS->>Secondary App (SMART Client): 
    Secondary App (SMART Client)->>SMART CHCS: GET /fhir/metadata
    SMART CHCS->>Secondary App (SMART Client): Describe Observation valueAttachments
    Secondary App (SMART Client)->>SMART CHCS: GET /observation?patient=123456
    SMART CHCS->>Secondary App (SMART Client): Observation valueAttachments
    Secondary App (SMART Client)->>Dr Debora: Display shared device data

CHCS as a SMART Client and Server

surfdoc commented 1 week ago

@minrk @ryanlovett @maryamv @fperez @scarini @jpp9 This is the WIP documentation for the September MVP. Once we have the link to the recording from today we can add that as well. We will plan on updating this issue as we update the documentation. Please feel free to tag folks that you feel would benefit from this information as well. Thanks.

ryanlovett commented 1 week ago

@surfdoc Thanks! Do you want to add this as a doc via PR, even in its WIP status? I'm guessing that MyST will be able to render it mostly as-is, including the mermaid diagrams. It'd probably be easier to update the doc as a file in the repo compared to editing it via the issue tracker. Since you're the ones making changes however, whatever is easiest for you.

surfdoc commented 1 week ago

@ryanlovett Yep. That is a much better idea that having it in an issue. I have created a PR and tagged you as a reviewer. Feel free to make any changes and updates. Thanks.