GraphQL access controls
# support
c
Have a few questions about GraphQL and access controls: - My understanding is that access controls are respected. Does GQL authentication work similarly to a regular API request? (i.e. for programmatic access, we would authenticate, then send an access token as
Bearer
header?) - For patient data access, is it straightforward to have the TS client impersonate a given patient/user for a given request? (This is more of a general question - but we have not yet got this far with regular API requests either). Not sure what constraints are placed on authenticating as a user - e.g. if we would need to pass in a password that we store in another database or something. Patients will not have access to these Medplum accounts - we would only use them to separate resources. - An alternative to using access controls like this would be to query with an administrative (or full read-only access) user - but always enforce a compartment for data. For example, even when querying for a single ID, use a search query with
(_compartment: "Patient/...", _id: "...")
. Do you see any drawbacks to this approach? A primary concern we have is the nested/cyclic nature of GQL - for example, if it were possible to query related patients from a parent resource a couple of layers deep (e.g. hypothetically, expand fields from all Patients who had visited a Location), we might inadvertently expose data outside of the compartment specified at the top level. Do you know if the top-level compartment specified on the GQL query cascades down to deeper layers? The example is contrived, but we want to be certain that it's not possible.
cc @jnak
r
Hi @codingtom - I'll answer each of these questions separately. I also think you could answer a lot of GraphQL questions by trying out our https://graphiql.medplum.com/ You can log into your own project and use the nextwork tab of your browser to inspect your queries.
> My understanding is that access controls are respected. Does GQL authentication work similarly to a regular API request? (i.e. for programmatic access, we would authenticate, then send an access token as Bearer header?) Yes Access controls are respected. Yes, authentication works like all other API requests,
> For patient data access, is it straightforward to have the TS client impersonate a given patient/user for a given request? (This is more of a general question - but we have not yet got this far with regular API requests either). Not sure what constraints are placed on authenticating as a user - e.g. if we would need to pass in a password that we store in another database or something. Patients will not have access to these Medplum accounts - we would only use them to separate resources. From the question, it's unclear what your specific setup is here. In general, we don't currently support the notion of the client changing it's authentication per-request, though this is something we've considered for server-to server communication (feel free to file an issue if this is of interest to you 😃 ) Medplum also supports basic authentication, and you can use the
MedplumClient.setBasicAuth()
method to set the basic authentication header on every request.
> An alternative to using access controls like this would be to query with an administrative (or full read-only access) user - but always enforce a compartment for data. For example, even when querying for a single ID, use a search query with (_compartment: "Patient/...", _id: "..."). Do you see any drawbacks to this approach? A primary concern we have is the nested/cyclic nature of GQL - for example, if it were possible to query related patients from a parent resource a couple of layers deep (e.g. hypothetically, expand fields from all Patients who had visited a Location), we might inadvertently expose data outside of the compartment specified at the top level. Do you know if the top-level compartment specified on the GQL query cascades down to deeper layers? The example is contrived, but we want to be certain that it's not possible. Yes you're concern is valid. We don't enforce the top-level
_compartment
parameter transitively, so I wouldn't recommend this
In general, you can find more information about the FHIR graphQL spec here: https://build.fhir.org/graphql.html
c
Thanks for the responses! Good to know about the non-transitive nature of
_compartment
- sounds like we will need to explore proper access controls here. I'm sure we can figure out a scheme for making requests with per-request credentials, this gives us enough to explore I think. Thanks!
@rahul1 sorry if I'm asking dumb questions here... Is it possible for a User to be linked to multiple profiles? I.e. could one user have multiple ProjectMembership to the same Project, linking to multiple Patients? Do queries then have visibility across those multiple compartments?
r
The way to do that is through Parametrized access policies. Basically a caregiver is given access to multiple Patient's data https://www.medplum.com/docs/auth/access-control#parameterized-policies-beta
j
Hi, to close the loop on this I wanted to let you know we decided pushing ACL into our GraphQL proxy layer. We needed to have a very dynamic ACL rules that we have already defined in our code / main operational DB, and we concluded it would be easier to just re-use that logic there. The alternative would have been to push all those rules and data into MedPlum by creating and keeping in sync pretty much a templated policy per user. Not only would it have been hard to get right because of its distributed nature, it would also have been very cumbersome to tweak that logic as it could have required to migrate all those parameterized policies one by one. Additionally, we were concerned about the potential of negative effects on MedPlum performance as we were not sure that the ACL system was designed to handle almost as many policies as users. Hope the context is useful!
164 Views