FHIR Chat · security questions · smart

Stream: smart

Topic: security questions


view this post on Zulip Vlad Ganshin (Sep 08 2021 at 21:06):

Hi all! Could you help me to understand some use cases of Smart on FHIR (v1)?

I have a FHIR Server on [base-url] and an Authorization Server on [auth-server]. And a user has an access to couple of Patients resources and their clinical data (pt-1 & pt-2).

1) Let's suppose that the user provided a grant to 3rd party app within next scope 'patient/Patient.read patient/Observation.read patient/Observation.write' and patient=pt-1 in context. As a 3rd party, what responses should I expect?

GET [base-url]/Patient/pt-1
GET [base-url]/Observation?subject=pt-1
GET [base-url]/Patient/pt-1/Observation

GET [base-url]/Patient
GET [base-url]/Patient/pt-2
GET [base-url]/Observation?subject=pt-2
GET [base-url]/Observation?subject=pt-3
GET [base-url]/Observation

POST [base-url]/Observation

subject:
  reference: Patient/pt-2

I believe that the first three requests should return 200 OK + data, and the rest of them 403 Unauthorized. Right? Or it depends on something?

2) Let's say we have not Observation, but CommunicationRequest resource. Which are search parameters available for 3rd party app within patient/CommunicationRequest.read scope? subject, sender, recipient, requester?

3) I'm thinking of building a tenant-based FHIR API which uses user-id as url prefix for every request.

[base-url]/user/<user-id>/Patient/pt-1 => 200 OK
[base-url]/user/<user-id>/Patient/pt-2 => 200 OK
[base-url]/user/<user-id>/Patient/pt-3 => 404 Not Found

I would say I have a lot of logical FHIR Servers on top of physical one. In case of EHR launch I could provide different iss parameters depending on the user who launched the app, so it could help me simplify access control module.

But I can't find an answer if it's possible to make something similar in case of Standalone launch. It seems like 3rd party app should know the only base-url and use it for every user? Is it possible to subsistute [base-url] somehow while launching?

view this post on Zulip Michele Mottini (Sep 08 2021 at 22:56):

For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle

view this post on Zulip Michele Mottini (Sep 08 2021 at 22:57):

(2) Which search parameter are available is unrelated to the scopes

view this post on Zulip Michele Mottini (Sep 08 2021 at 22:58):

(3) Don't think that would work, clients expect a fixed URL to connect to

view this post on Zulip Vlad Ganshin (Sep 09 2021 at 07:18):

(1.1) We have the same solution for now, but I'm not sure if it's correct using Authorization header as an implicit parameter for business logic. Will my server be conformant with FHIR Specification (which is RESTful) if it provides different responses on the same url depending on Authorization header? I believe, that according to REST, the role of Access Conrol is only accept/reject requests, but not influence on the result. So, I would say that in this case our FHIR Servers are not conformant with FHIR Specification. Is it correct, or I miss something?

(1.2) And what about saving resources (POST/PUT/PATCH)? Should my FHIR Server set reference to the patient implicitly or validate and require correct reference value in the body?

(2) From the smart app developer point of view, how should I understand which endpoints (or/and search parameters) are available within a specific scope I got from user? Does specification have this answer, or I have to adopt my application to every specific FHIR Server?

(3) I feel that the specification tries to connect Smart App Developer and FHIR Server Developer and it provides a concrete authentication flow. But as a Smart App dev, once I have a token, I don't see my capability within my scopes. And as FHIR Server dev I don't see a standard way to provide such capabilities.

So, once FHIR Server provided 'patient/Patient.read patient/Observation.*' scope, does it obligated to accept requests to [base-url]/Patient/<pt-id>, [base-url]/Observation, etc?

Will my server be conformant with FHIR if I just say in documentation, that within patient/... scopes smart app should use another base-url. e.g. [base-url]/patient/<pt-id> ([base-url]/patient/«pt-id>/Patient/<pt-id>, [base-url]/patient/<pt-id>/Observation).

view this post on Zulip John Moehrke (Sep 09 2021 at 12:17):

http://hl7.org/fhir/security.html#AccessDenied

view this post on Zulip John Moehrke (Sep 09 2021 at 12:18):

policies are important. principles of REST do not override policies.

view this post on Zulip Josh Mandel (Sep 09 2021 at 12:55):

In general with smart, it is okay for a server to reject a query prospectively/statically because of scopes. It is also okay for a server too simply redact results because of scopes. We don't have prescriptive behavior on this. The only thing it's not okay to do is return data beyond what the scopes allow.

view this post on Zulip Josh Mandel (Sep 09 2021 at 12:56):

The question of what endpoints are available is somewhat orthogonal to your scopes. For example, a server might advertise in its documentation or in its capability statement that it supports a "batch" endpoint; if it does, clients can call this end point with requests that are consistent with the available scopes. If it does not, clients can't.

view this post on Zulip nicola (RIO/SS) (Sep 09 2021 at 13:48):

I wonder SMART on FHIR based on baseUrl convention instead of more flexible HATEOAS. Why server after auth could not just return explicit baseUrl for the client with access_token ?

{
  access_token: ....
  fhirBaseUrl: ....
}

view this post on Zulip nicola (RIO/SS) (Sep 09 2021 at 13:52):

Compartments like /Patient/<id>/{metadata,Observation,Encounter} look like good fit for SMART Clients and Servers.

view this post on Zulip Vlad Ganshin (Sep 09 2021 at 13:52):

Thank you! I do missed that part in Access Denied Response Handling chapter.

Just to clarify, if I have a FHIR Server which is rich on capability, it is ok to restrict some access depending on client type, not only scopes provided to that client, isn't it?

view this post on Zulip Josh Mandel (Sep 09 2021 at 13:56):

That would work for areas like the patient compartment where fhir explicitly defines some context, but the mapping breaks down pretty quickly too. For example even with "patient" compartments, a smart app authorized to access data about a given patient might be able to see certain data outside of a compartment, such as data directly linked from or needed to interpret the data in the compartment. So passing the patient id (or fhirContext[] as array of references as proposed in SMARTv2) has been a flexible choice.

view this post on Zulip nicola (RIO/SS) (Sep 09 2021 at 13:56):

Michele Mottini said:

For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle

Should not server respond with 403 for (1)?

view this post on Zulip nicola (RIO/SS) (Sep 09 2021 at 13:58):

Josh Mandel said:

That would work for areas like the patient compartment where fhir explicitly defines some context, but the mapping breaks down pretty quickly too. For example even with "patient" compartments, a smart app authorized to access data about a given patient might be able to see certain data outside of a compartment, such as data directly linked from or needed to interpret the data in the compartment. So passing the patient id (or fhirContext[] as array of references as proposed in SMARTv2) has been a flexible choice.

What is fhirContext?

view this post on Zulip nicola (RIO/SS) (Sep 09 2021 at 14:00):

We are thinking about "poko yoko" for Smart on FHIR apps - i.e. implicitly inject patient id into all search and even CRUD operations.

view this post on Zulip nicola (RIO/SS) (Sep 09 2021 at 14:01):

@Josh Mandel what is your opinion about such an implicit server behavior?

view this post on Zulip Josh Mandel (Sep 09 2021 at 14:44):

nicola (RIO/SS): Michele Mottini said:

For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle
Should not server respond with 403 for (1)?

From the SMART spec perspective, both of these are OK behaviors.

view this post on Zulip Josh Mandel (Sep 09 2021 at 14:45):

What is fhirContext?

See FHIR-32253; this is being added to resolve SMARTv2 ballot feedback

view this post on Zulip Josh Mandel (Sep 09 2021 at 14:47):

nicola (RIO/SS): We are thinking about "poko yoko" for Smart on FHIR apps - i.e. implicitly inject patient id into all search and even CRUD operations.

I like this, but there are edge cases where it'll prevent access that a client should have (e.g., with patient/*.cruds access, you might still be allowed to issue a query like GET /Observation/123 where the subject of the observation is something other than the patient (say, a patient's device or location).

view this post on Zulip nicola (RIO/SS) (Sep 10 2021 at 08:10):

Michele Mottini said:

For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle

I think for (1) - 403 is more honest - otherwise, the client may be confused and interpret the empty response as a lack of data

view this post on Zulip Michele Mottini (Sep 10 2021 at 13:43):

I think no error is better. Using 403 is actually _leaking_ the information that there is data that the client cannot see

view this post on Zulip David Pyke (Sep 10 2021 at 13:46):

Yep, if they're fishing for information, a 200 tells them nothing, a 403 says there's data which is a problem from a privacy point of view

view this post on Zulip John Moehrke (Sep 10 2021 at 13:51):

AND this is why the actual value returned should be driven by POLICY. http://hl7.org/fhir/security.html#AccessDenied


Last updated: Apr 12 2022 at 19:14 UTC