SMART: Assigning Permissions
Assigning appropriate permissions is one of the more challenging aspects of building a SMART on FHIR application. This page explores some of the challenges and offers potential implementation options. It is important to consider that no two applications are the same, and every deployment scenario will have its own unique quirks. You are always welcome to discuss these options with the Smile CDR team if you would like assistance in planning out an appropriate security model for your system.
When a user authorizes with an application, there are two sets of permissions that must be considered: The Client Scopes that are granted to the client, and the User Permissions that are granted to the user.
The permissions that are ultimately available to the user via the client session once they have successfully authorized will be the intersection of these two concepts.
For example, consider a user who has only been granted the FHIR_READ_ALL_IN_COMPARTMENT/Patient/123
permission in their user account, but has not been granted any other permissions. This permission allows the user read-only access to resources associated with their Patient resource (Patient/123).
Now, suppose this user authorizes a client application with the patient/*.read
and patient/*.write
scopes. Despite these broad scopes being authorized, Smile CDR will only allow the client to perform actions that are within the intersection of the scopes and permissions. In this case, the client/user will only be permitted to read data associated with the given Patient and will not be allowed to write.
On the other hand, suppose the user had been granted the very broad ROLE_FHIR_CLIENT_SUPERUSER
permission. This permission allows the user mostly unrestricted access to perform FHIR operations. However, if the user grants a client only the patient/*.read
scope, the client will not be permitted to perform any write actions against the FHIR services.
When authorizing applications used by Patients, a common scenario is to have a user account bound to a specific Patient resource in FHIR storage. In this scenario, generally an individual Patient user should only be able to access data that belongs to them.
When authorizing such a user for a patient-facing app, there are two objectives to meet:
Objective 1: The Smile CDR FHIR Endpoint needs to know whether the user should have be permitted access the specific FHIR resources it is trying to access. In the case of a patient/consumer user this often means that the user should only have access to data linked to the specific Patient resource corresponding to the user. Patient/consumer users might also have access to data linked to other Patient resources, such as family members who have consented, people for whom they are a caregiver, etc.
Objective 2: The App needs to know which Patient resource the user's account corresponds to, so that the App knows which resources are appropriate to request from the FHIR endpoint. In other words, if the app has just completed an auth flow and now has an access token for user john1988, it needs to know that this user has permission to access data linked to the FHIR resource Patient/123 and possibly other as well. It may also need to understand that this Patient resource actually corresponds to the logged in user.
When using the Local Inbound Security module, permissions may be assigned directly to individual users, so this is a common approach. Users may be created with appropriate permissions for the data that they are allowed to access directly assigned to their account. For example, a user might be assigned FHIR_READ_ALL_IN_COMPARTMENT/Patient/123
and FHIR_WRITE_ALL_IN_COMPARTMENT/Patient/123
permissions, indicating that they have access to this Patient and its linked data.
This solves Objective 1, but does not solve Objective 2. A common solution for Objective 2 is to communicate details about the appropriate Patient resource for access via the Launch Context Scopes.
The most common way to accomplish this with Smile CDR is to store an attribute in the user's account that contains the ID of the Patient resource corresponding to their record. In the case of an internally issued access token (i.e. using the SMART Outbound Security module) this can be added to the user session by a script in the Local Inbound Security module (or the LDAP/Script/etc. Inbound Security module). In this case, Objective 1 is met by assigning appropriate permissions during the authorization stage (e.g. by assigning them directly to the user's account, or by enriching the permissions via a login script). Objective 2 can be met using launch scopes.
When federating to an external user directory, a common approach is to store a custom attribute of some sort along with the other user details in the directory. This attribute might take the form of an LDAP attribute or group membership, or could be a value retrieved by a login script that is calling an external HTTP service.
In the case of an externally issued access token (i.e. using a third-party Authorization Server such as Keycloak) the identity of the Patient should be stored in the Authorization Server user record, so that it can be communicated to the FHIR Endpoint via a claim in the Access Token. This satisfies Objective 1 by allowing the SMART Inbound Security module login script to decode and inspect the token to extract the patient ID, then assign appropriate permissions. This also satisfies Objective 2 by allowing the app to decode and inspect the token to extract the patient ID.
This raises an additional challenge: how to add this attribute to the Authorization Server user directory. This will be different depending on the specific OIDC server being used, and the type of signup flow you are using.
If the application has accounts managed by a central authority rather than allowing users to self-register (this is often the case in institutional applications, research trial applications, etc.) then an additional step can be added to the user account creation process that creates a Patient resource, and then assigns its ID to the user account.
If the application will allow direct user sign up and FHIR resources already exist in the FHIR repository, a manual/automatic linking process may need to be developed that inspects a user's account and looks for a FHIR resource with the same attributes (e.g. a common identifier or demographic, such as a medical record number or an email address).