201709 Consumer Centered Data Exchange
Consumer Centered Data Exchange
Submitting WG/Project/Implementer Group
FHIR Product Director, in association with Society for Participatory Medicine, MIHIN, NATE, DXC. Interested committees: FHIR-I, CBCC, Security, PA, PC, OO
Justification
In the connectathon process, we've tested narrow scenarios around data exchange, but interest is growing quickly to understanding the Consumer Centered Directed Exchange.
Consumer Centered Directed Exchange can be thought of as a category of use cases including:
- Consumer Access - in these use cases data held by a Source EMR is transferred to a Consumer Controlled App (CCA).
- Consumer Mediated Exchange - in these use cases data held by a CCA is transferred to a Target EMR
- Consumer Directed Exchange - in these use cases the actions of a Consumer (via registering a Consent Resource or via UMA-based methods) authorizes the transfer of data from the Source EMR to the Target EMR
The justification for this track is to develop an understanding of what - if anything - the main specification or the US core IG should say about them
Proposed Track Lead
Grahame Grieve (mentoring Aaron Seib to take over after this)
Expected participants
NATE MIHIN DXC (others: email aaron.seib@nate-trust.org if you are interested in getting involved)
Scenario
Paul is a VA beneficiary living in Alaska. Because of the remoteness of his location, there aren’t a lot of specialists at his local VA facility for him to see and as a result Paul frequently gets referred to local civilian specialists outside of the VA. Following specialist visit(s) Paul would like to ensure that the PHI generated by the specialist as a result of the encounter is shared with his providers at the VA. Thus, there is a need to transfer information from the specialist to the VA record that his VA Providers access.
Paul uses a Consumer Controlled Application (CCA) where he is able to maintain records from all of his providers in one place.
Paul would like to cause relevant EMR data to be transferred from the specialist's system (the Source EMR) to the VA's EMR (the Target EMR).
The scenarios being proposed in this track describe several methods that may enable Paul "to cause" this transfer.
Assumptions: we intended to reuse and extend as necessary existing capabilities developed to date by the FHIR-community including
- the Argonaut interface - leverage the ability to data from an EMR that is provided by Argonaut based patient portals;
- SMART-on-FHIR and\or Sync-for-Science (a constrained instance of SMART-on-FHIR);
- Various FHIR resources such as the Consent resource; and
- Others as identified.
- Paul uses a Consumer Controlled Application (CCA) where he is able to maintain records from all of his providers in one place.
See Relevant Specs and Documentation below.
Roles
- Consumer Controlled App: the CCA of Paul's choice
- Source EMR system: the provider of data that will be made available (a specialist EMR)
- Target EMR system: the VA or equivalent system that will acquire the data
- 3rd Party Endorsements service - a service that publishes FHIR-Based Endorsement resources which are relied upon when a use case performs "Application Verification"
Authorization pattern
There are 7 possible patterns for Authorising/Managing the data flow
1. Provider to Provider CCDE 2. Provider to Provider with Consumer Consent CCDE 3. Provider to Provider with Consent Direct-based Push 4. Provider to Consumer under Individual Right of Access via Direct-based Push 5. Provider to Consumer FHIR-based Consumer Access 6. Consumer to Provider FHIR-based Consumer Mediated Exchange 7. Full UMA
1. Provider to Provider CCDE
Data is made available to a target EMR by the normal SMART on FHIR interface (see http://docs.smarthealthit.org/authorization/). In this scenario:
- Paul logs into the target EMR app (either EHR or standalone launch), and informs the app that he wants to connect it to the source EMR (how this is done is outside the scope of the connectathon)
- The target EMR app (re)directs Paul to the authorization URL on the source EMR
- Paul authorizes the application as he wants
- the target EMR makes requests of the source system in an ongoing fashion per SMART on FHIR
- Paul connects to the source EMR to revoke his authorization when he wants the data flow to end
This scenario requires Paul to know the URLs for both source EMR and the target EMR, he must deal with multiple applications, and is dependent on Trust Already Existing between the Source and Target EMR.
Notes:
- there is no new API/interface in this arrangement - all of this is as described today, with additional application work.
- this is actually more complicated than a simpler alternative: Paul has an application that downloads content from the source, and uploads it to the target. This approach has 2 problems - there's no trust (provenance) associated with the target/source connection (and there's plenty of real world demonstration that this is a big problem for care providers) and flow of data depends on Paul's devices and connectivity. There is solid grounds for Paul being able to download/update data to EMRs, but this connectathon stream focuses on giving the customer control over direct data flow
Assumptions for this Connectathon If a standalone app is being used it is already registered with the source EMR
2. Provider to Provider with Consumer Consent CCDE
Data is made available by the normal SMART on FHIR interface with a consent layer.
In this scenario:
- Paul authorizes an app to the source EMR (http://docs.smarthealthit.org/authorization/)
- Paul posts a Consent resource to the server, or chooses an existing consent statement (details of how this will be down are outside the scope of this connectathon, a stand-in stantion will be used for this connectathon)
- Paul asks the source server for an API token based on the consent (see 'Acquiring an API token' below)
- Paul authorizes with the target server, and gives it the API token (see 'Providing API token' below)
- the target EMR makes requests of the source system in an ongoing fashion using the API token
- Paul can revoke the authorize by revoking the token (see 'Revoking an API token' below)
This scenario requires Paul to know the URLs for both source and target, and to have apps authorized to both of them (could be the same app) but he doesn't have to deal with multiple applications, and trust relationships between them are not required
3. Provider to Provider with Consent Direct-based Push
In this scenario, data is made available in the same format as Argonaut, but instead of a Pull based API, a push using Direct is used instead.
In this scenario:
- Paul authorizes a target EMR to the source EMR (standard SMART on FHIR)
- Paul posts a Consent resource to the server, or chooses an existing consent statement
- Paul asks the source EMR to start pushing the data based on the consent (see 'Starting push' below)
- the source EMR sends data to the target EMR using direct based push
- Paul can stop the sending through the source EMR (see 'Stopping push' below)
This scenario requires Paul to know the URLs for the source, and the right direct email address for the target, and direct support must exist for the transfer between source and target. Paul doesn't have to have any relationship with the target, deal with multiple applications, and trust relationships between them are not required
4. Provider to Consumer under Individual Right of Access via Direct-based Push
In this scenario, data is made available in the same format as Argonaut, but instead of a Pull based API, a push using Direct is used instead.
In this scenario:
- Paul authorizes his CCA to the source EMR (standard SMART on FHIR)
- Paul posts an Individual Right of Access request to the server - Does the Consent resource satisfy the requirements of an IRA?
- Paul asks the source EMR to start pushing the data based on the consent (see 'Starting push' below)
- the source EMR sends data to the his CCA using direct based push
- Paul can stop the sending through the source EMR (see 'Stopping push' below)
NOTE: Opportunity to explore how Direct could be used as send an IRA from a CCA to the sEMR's "Consent Server" is a potential corollary to this scenario.
5. Provider to Consumer FHIR-based Consumer Access
Data is made available to a target EMR by the normal SMART on FHIR interface (see http://docs.smarthealthit.org/authorization/).
In this scenario:
- Paul logs into the CCA , and informs the app that he wants to connect it to the source EMR (how this is done is outside the scope of the connectathon)
- The CCA (re)directs Paul to the authorization URL on the source EMR
- Paul authorizes the application as he wants
- the CCA makes requests of the source system in an ongoing fashion per SMART on FHIR
- Paul connects to the source EMR to revoke his authorization when he wants the data flow to end
This scenario requires Paul to know the URLs for both source EMR and the target EMR, he must deal with multiple applications, and is dependent on Trust Already Existing between the Source and Target EMR.
6. Consumer to Provider FHIR-based Consumer Mediated Exchange
This scenario is similar to scenario 2 except instead of data flowing from the Source EMR to the Target EMR (Institution to institution) a Consumer Controlled Health App is the Source. With the Consumer directing the flow of data a consent layer is not required but to support the Target EMR’s trust in the Consumer App we invoke Application Verification when the target EMR may wish to verify that the Consumer App identified in the $authorize operation is acceptable to it. To do this, the target EMR can take the public key provided in the "publicKey" parameter of the $authorize operation, and sends it to a 3rd party server that it trusts to provide advice similar to the interactions between a Source and Target EMR in scenario 2. In this scenario a precondition is that the Consumer Controlled App has content that the consumer wishes to share with the target EMR.
- Paul authorizes his consumer controlled app (CCA) to release selected content to a target EMR
- Paul asks the CCA’s server for an API token based on the consent (see 'Acquiring an API token' below)
- Paul gives the target server the API token (see 'Providing API token' below) and the “publicKey” of the CCA
- The target EMR invokes Application Verification using the “publickey” and a local policy engine to determine if it “trust” the Consumer App for this use case.
- The target EMR makes requests of the CCA (which implies to me that this could be discovered via the same registry as the one used to check for endorsements) for the content using the API token.
This scenario requires Paul’s CCA to know the target EMR’s URL for this use case (CDE). This scenario also requires the target EMR to know the location of the 3rd party server that Paul’s CCA is registered with to retrieve the endorsements associated with that CCA for evaluation by the target EMR’s local policy engine.
7. Full UMA
Data is made available by the normal Argonaut interface, but the authorization has been delegated to a central server that manages the patient Authorization per the HEART/UMA specification.
- Paul grants target EMR (the VA) access to his data through the UMA Authorization Server's grant management interface
- Target EMR initiates UMA-based authorization by requesting access to Paul's protected data on the source EMR
- Source EMR contacts AS to obtain an UMA permission ticket, then returns a 403 Unauthorized response to the target EMR containing this permission ticket and the URL for the AS
- Target EMR asks the AS to exchange the permission ticket for a requesting party token (RPT)
- AS authenticates target EMR and issues RPT to target EMR
- Target EMR uses RPT as bearer token to access the protected data from the source EMR in an ongoing fashion
- Paul can revoke target EMR's access through AS grant management interface
Note: this builds on the Argonaut interface by adding HEART/UMA support to it. This scenario requires the target EMR to know the source EMR’s FHIR URL, but knowledge of the UMA AS URL is not required. The source EMR has previously delegated authorization to Paul's data (resource set) to the UMA-enabled AS and the AS is able to authenticate the target EMR.
Interfaces
For pattern #2 - Provider to Provider with Consent CCDE
Authorizing an Application
POST [base]/Consent/[id]/$authorize
Inbound Parameters:
- publicKey : string - a PEM encoded RSA public key that identifies the application that is being authorized to act on behalf of the user (see below for how to get that)
- duration : Duration - how long the token should be good for. (optional: default to Consent.period if not provided) (cannot be be for longer than the consent itself)
Response: 200 ok with Parameters, or an error with an operation outcome. Outbound Parameters:
- duration : Duration - maximum length of time that the token is going to be honored. No duration means that the approval is not time limited
The server returns an error if it is not able to understand the consent resource fully, or if it is not prepared to honor the consent statement (e.g. it probably won't agree to a consent that grants more than the granting application itself has been authorized to have), or if it refuses to authorize the specified application for some reason (see below for further discussion on the implementation and policy of this).
For the purposes of this connectathon, this is the suggested profile on the Consent Statement:
<Consent xmlns="http://hl7.org/fhir"> <id value="[id from api]"/> <text> // as appropriate // </text> <status value="active"/> // can only perform $getToken on active consent statements // <patient>// patient data to be shared //</patient> <period>// optional period //</period> <dateTime value="[optional]"/> <actor> // text/code description of who's going to be granted access. This is useful for describing the recipient, but won't have any computed meaning // </actor> <organization>// good to fill this out for consumption, but not important //</organization> <policyRule value="http://hl7.org/fhir/ConsentDefinition/simple-oauth"> <purpose> // optional but not processed //</purpose> <dataPeriod>// optional, enforced if present //</dataPeriod> // don't use this // <except> // the definition of http://hl7.org/fhir/ConsentDefinition/simple-oauth is that only this consent statement is granted access. Anything else is granted access by exception // <type value="permit"/> // not used <period/>, <actor/> // <action> // this consent grants the right to access data // <coding> <system value="http://hl7.org/fhir/consentaction"/></coding> </action> // not used <securityLabel/>, <purpose/> // // repeat class for each Smart on FHIR scope // <class> <system value="http://smarthealthit.org/fhir/scopes"/>
</class> // not used
, <dataPeriod/>, // </except> </Consent>
Notes:
- This profile is a restricted form of the Consent resource that allows the user to consent using Smart on FHIR scopes
- Systems that don't allow upload of consent, but allow $authorize, can use whatever consent they can understand - the client does not need to understand the consent details to call $authorize.
- JCM note: this is confusing. How would the clint know which cosnent resource to use if it can't understand the details?)
- GG response: User chooses from a list
- JCM note: this is confusing. How would the clint know which cosnent resource to use if it can't understand the details?)
- this connectathon defines the special Smart on FHIR scope "operation/Consent.authorize" that a client can ask for to indicate that it wishes to use the token management API described here in addition to read and/or write of Consent resources.
- (JCM note: I updated the name of this scope.)
- umm, ok, but it's for more than just Authorize - it does deauthorise, etc. hence why I gave it a more generic name
Acquiring an Applications JWT
The operation above requires that the client have a public key that identifies the target EHR. If the target EHR supports OpenID Connect, then the client can discover this key by retrieving "/.well-known/openid-configuration" and looking for the "jwks_uri" property. (Note: a missing link is that we don't have a clear way to discover the OpenID Connect base URI, aka issuer URI, from the SMART on FHIR Conformance statement.)
Application Verification
The source EMR may wish to verify that the target EMR identified in the $authorize operation is acceptable to it. To do this, the source EMR can take the public key provided in the "publicKey" parameter of the $authorize operation, and send it to a 3rd party Endorsements Service that provides information about what endorsements are verifiably attributed to the target EMR.
[Details regarding the API used to access the 3rd Party Endorsements Service, parameters to be passed (including "publicKey" and potentially other info such as endorsement type or use case) and the response set to be defined]
If, after considering the response from the advisor, the EMR declines to honor the user's request, it responds to the $authorize operation with an error.
Notes
- The degree to which a source EMR is required/allowed to verify the target EMR is an open policy question. This connectathon is not taking any policy position on this, only establishing infrastructure to support various possible policy positions
- validating the target EMR is an operation that can be carried out at any time, not just when the application is first authorized (see Revoking an API token below)
- for this connectathon, no security is applied to this operation. Future iterations of the connectathon stream will consider security questions, and extensions to the application verification functionality described here
Providing API token
Once an application has been authorized, the user informs it by calling the $connect operation:
POST [base]/$connect
Inbound parameters:
- url: uri - the end-point URL for the Argonaut/S4S end-point of the application that it is authorised to acquire data from
- Consent : id: the resource id of the consent statement on the source system. Required read-only access, so the target knows what is authorized to access
- duration : Duration - maximum length of time that authorization has been granted going to be honored
- patient : id: the resource id of the patient on the target system that records are for (optional; default is the single patient associated with the authentication with the target application - it's an error if there's more than one)
- publicKey : string : the PEM encoded public key that has been authorized.
- (JCM note: I added this to the list because I think it's better to include it explicitly. This helps in the case wehre a target system has >1 public key listed in its JWKS.)
- GG response: well, that depends on the resolution of the other subject. but ok, same parameter as on authorize so it knows
Response: 200 ok or an error with an operation outcome
Acquiring Data from the Source EMR
Once authorized, the target EMR creates a JWT token:
{ "iss": "[same identity as in the JWT above", "aud": "[token end-point of source EMR]", "exp": [short term period], "jti": "[some nonce]", "consent": "[id]" }
and then submits this to the normal token end point (see SMART on FHIR documentation), but with a different set of parameters:
grant_type urn:ietf:params:oauth:grant-type:jwt-bearer assertion={authz JWT}
The response is the standard SMART on FHIR access token response.
Notes:
- the client (target EMR) does not specify any scopes in this case. Scopes are dictated by the consent resource
- Searching on Patient on the source system using this API token will only match the Consent.patient, and only resources in that patient compartment are available
Revoking an API token
getting a list of tokens:
GET [base]/Consent/[id]/$authorizations
Response 200 ok with parameters:
- token - tuple
- app-id : url - previously authorized application ("iss" header from the JWT)
- duration : Duration - how long the token is good for
- error : String - errors associated with this authorization (typically, the user make an authorization but the EMR is no longer prepared to honor it for some reason)
Revoking a Token:
POST [base]/Consent/[id]/$revokeAuthorization
Inbound parameters:
- app-id : url - the identity of a previously authorized application
- (JCM Note: I'd update $authorizations and $revokeAuthorization to use "publicKey" instaed of "app-id").
- GG response: same discussion
Response: 200 ok or an error with an operation outcome
Note: any further use of tokens associated with this authorization will result in a 404 unauthorized response
For pattern #4 - Direct push
Starting push
POST [base]/Consent/[id]/$pushStart
Inbound Parameters:
- duration : Duration - how long the application should push data for. (optional: default is system should push data until otherwise instructed)
- address : uri - direct address (email address) where the data should be sent
Response: 200 ok with Parameters, or an error with an operation outcome. Outbound Parameters:
- address : uri - where the data is going to be sent
- duration : Duration - maximum length of time that the token is going to be honored. If this is missing, the source will send until otherwise installed
The server returns an error if it is not able to understand the consent resource fully, or if it is not prepared to honor the consent statement (e.g. it may not agree to a consent that grants more than the granting application itself has been authorized to have). The server may also return an error if it cannot or will not send to the nominated direct address
For the purposes of this connectathon, this is the suggested profile on the Consent Statement:
<Consent xmlns="http://hl7.org/fhir"> <id value="[id from api]"/> <text> // as appropriate // </text> <status value="active"/> // can only perform $getToken on active consent statements // <patient>// patient data to be shared //</patient> <period>// optional period //</period> <dateTime value="[optional]"/> <actor> // text/code description of who's going to be granted access. This is useful for describing the recipient, but won't have any computed meaning // </actor> <organization>// good to fill this out for consumption, but not important //</organization> <policyRule value="http://hl7.org/fhir/ConsentDefinition/simple-oauth"> <purpose> // optional but not processed //</purpose> <dataPeriod>// optional, enforced if present //</dataPeriod> // don't use this // <except> // the definition of http://hl7.org/fhir/ConsentDefinition/simple-oauth is that only this consent statement is granted access. Anything else is granted access by exception // <type value="permit"/> // not used <period/>, <actor/> // <action> // this consent grants the right to access data // <coding> <system value="http://hl7.org/fhir/consentaction"/></coding> </action> // not used <securityLabel/>, <purpose/> // // repeat class for each Smart on FHIR scope // <class> <system value="http://smarthealthit.org/fhir/scopes"/>
</class> // not used
, <dataPeriod/>, // </except> </Consent>
Notes:
- This profile is a restricted form of the Consent resource that allows the user to consent using Smart on FHIR scopes
- Systems that don't allow upload of consent, but allow $pushRecords, can do whatever consent they can understand - the client does not need to understand the consent details to call $pushRecords.
- this API is also controlled by the FHIR scope "Consent/flow" that a client can ask for to indicate that it wishes to use the Push API control described here in addition to read and/or write of Consent resources
When the system sends data by direct, it should use the profile as described by Sending FHIR resources in Direct Messages. Data is sent as collections, when ever the data is available, batched by sending system convenience.
Stopping push
Clients can find what push processes are set up for a given consent resource:
GET [base]/Consent/[id]/$listPush
Response 200 ok with parameters:
- token - tuple
- address : uri - address data is being sent to
- status : string - current status for human discussion - number of records sent, or current error message, as appropriate
Stopping a push:
POST [base]/Consent/[id]/$pushStop
Inbound parameters:
- address : uri - Direct address to stop sending to
Response: 200 ok or an error with an operation outcome
Data will stop flowing once a 200 is returned
Relevant Specs, Documentation and Test Servers
- Sync For Science FHIR API Calls (http://syncfor.science/api-calls/)
- Sync For Science reference stack and demonstration (https://demo.syncfor.science/)
- a specification for authorization, based on OAuth 2 (details at http://docs.smarthealthit.org/authorization/)
- a specification for data access, based on FHIR (details generally at http://docs.smarthealthit.org/ with details about data profiles at http://www.fhir.org/guides/argonaut/r2/)
- Publicly Available FHIR Servers for testing: (http://wiki.hl7.org/index.php?title=Publicly_Available_FHIR_Servers_for_testing)