LegitimateInterest
This validator checks if the client has a legitimate interest to the resource that it is requesting. The checks for this depend on the client's role.
If the client is a patient, the validator essentially behaves like the PatientCompartment validator with a few additions:
- The
Organizationentity assigned viaPatient.managingOrganizationis allowed. - Every
Practitionerentity which has an active role inPatient.managingOrganizationis allowed. - Every
PractitionerRoleentity which belongs toPatient.managingOrganizationis allowed.
If the client is a practitioner, the validator builds something like an "organization compartment". The organization compartment consists of all entities that are linked to the organization. This includes all patients that have set the Patient.managingOrganization property to the corresponding organization, as well as all records in the corresponding patient compartments.
A practitioner has access to all organization compartments in which they have an active role. The configuration can optionally specify a mandatory role code and system that needs to be present. This way, it is possible to model scenarios where only someone with an "ict" role can create new practitioners for an organization but can not read any patient data, while someone with a "doctor" role can read and write patient data but not create practitioners or change other organizational entities.
When specifying practitioner role codes, both system and code must be specified. Specifying only one value will produce unexpected results.
The validator is powerful but also quite expensive to run. To speed it up, it caches internal requests to the data it needs, such as practitioner roles, organizations and patient entities. The cache has a default, short-lived timeout of 2 minutes but this also means that updates to permissions (such as when changing a practitioner role) will not be effective immediately.
If you route read operations through this validator, it makes sense to also route write operations concerning the same role and the same entity through this validator. That way, the validator has the possibility to clear its cache whenever entities are changed. (automated cache invalidations are not implemented yet)
It is important to note that this validator is not intended to replace the PatientCompartment or PractitionerCompartment validators. It is intended to give implementers the ability to express different ways to validate access. It is preferable to use the compartment validators if they achieve the same thing.
NOTE: For resource creation requests, where a legitimate interest cannot be established for the client that is making that request an unauthorized response is returned. For resource creation, explicitly define a rule that allows that.
Validation Strategy Per Entity
The table below lists the validation strategies per entity and per role. The following definitions apply:
ActiveOrganizations = PractitionerRole.where(practitioner == Practitioner.id && active == true).organizationPractitionerclients need to have an affiliation with an organization that owns or manages the requested record.- Where a compartment specifies multiple potential relationships, only one is supported in the code at the moment.
- Compartment validations noted with
!!are currently non-functional due to how look-ups are implemented. (related ticket)
| Entity | Practitioner Role | Patient Role |
|---|---|---|
| Account | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| AdverseEvent | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| AllergyIntolerance | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| AppointmentResponse | actor.managingOrganization in ActiveOrganizations | PatientCompartment |
| Appointment | !! PatientCompartment | |
| AuditEvent | !! PatientCompartment | |
| Basic | PatientCompartment | |
| BodyStructure | PatientCompartment | |
| CarePlan | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| CareTeam | PatientCompartment | |
| ChargeItem | PatientCompartment | |
| ClaimResponse | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| Claim | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| ClinicalImpression | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| CommunicationRequest | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Communication | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Composition | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Condition | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Consent | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| Contract | subject.managingOrganization in ActiveOrganizations | OrganizationCompartment |
| CoverageEligibilityRequest | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| Coverage | beneficiary.managingOrganization in ActiveOrganizations | PatientCompartment |
| DetectedIssue | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| DeviceDefinition | owner in ActiveOrganizations | owner = managingOrganization |
| DeviceRequest | PatientCompartment | |
| DeviceUseStatement | PatientCompartment | |
| Device | owner in ActiveOrganizations | owner = managingOrganization |
| DiagnosticReport | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| DocumentManifest | PatientCompartment | |
| DocumentReference | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Encounter | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| EnrollmentRequest | candidate.managingOrganization in ActiveOrganizations | PatientCompartment |
| EnrollmentResponse | OrganizationCompartment | |
| EpisodeOfCare | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| ExplanationOfBenefit | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| FamilyMemberHistory | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| FhirGroup | !! PatientCompartment | |
| Flag | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Goal | subject..managingOrganization in ActiveOrganizations | PatientCompartment |
| GuidanceResponse | subject.managingOrganization in ActiveOrganizations | OrganizationCompartment |
| HealthcareService | providedBy in ActiveOrganizations | providedBy = managingOrganization |
| ImagingStudy | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| ImmunizationEvaluation | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| ImmunizationRecommendation | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| Immunization | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| InsurancePlan | ownedBy in ActiveOrganizations | ownedBy = managingOrganization |
| Invoice | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Location | managingOrganization in ActiveOrganizations | managingOrganization = managingOrganization |
| MeasureReport | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Media | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| MedicationAdministration | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| MedicationDispense | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| MedicationRequest | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| MedicationStatement | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| MolecularSequence | PatientCompartment | |
| NutritionOrder | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| Observation | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| OrganizationAffiliation | organization in ActiveOrganizations | organization = managingOrganization |
| Organization | id in ActiveOrganizations | Organization = Patient.generalPractitioner or Organization = Patient.managingOrganization |
| Patient | managingOrganization in ActiveOrganizations | identity resource |
| PaymentNotice | provider in ActiveOrganizations | provider = managingOrganization |
| PaymentReconciliation | requestor in ActiveOrganizations | requestor = managingOrganization |
| Person | managingOrganization in ActiveOrganizations | !! PatientCompartment |
| PractitionerRole | organization in ActiveOrganizations | PractitionerRole = Patient.generalPractitioner or PractitionerRole.organization = Patient.managingOrganization |
| Practitioner | role.organization in ActiveOrganizations OR id == self | Practitioner = Patient.generalPractitioner or OrganizationCompartment |
| Procedure | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Provenance | !! PatientCompartment | |
| QuestionnaireResponse | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| RegulatedAuthorization | holder in ActiveOrganizations | holder = managingOrganization |
| RelatedPerson | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| RequestGroup | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| ResearchStudy | sponsor in ActiveOrganizations | sponsor = managingOrganization |
| ResearchSubject | individual.managingOrganization in ActiveOrganizations | PatientCompartment |
| RiskAssessment | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Schedule | PatientCompartment | |
| ServiceRequest | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| Specimen | subject.managingOrganization in ActiveOrganizations | PatientCompartment |
| SupplyDelivery | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
| SupplyRequest | supplier in ActiveOrganizations | PatientCompartment |
| VisionPrescription | patient.managingOrganization in ActiveOrganizations | PatientCompartment |
Role Inheritance
The setting legitimateInterestRoleInheritanceLevels in the configuration file controls if roles in an organization should be inherited to child organizations. This supports the following use cases:
- A hospital can be broken down into multiple independent units where general staff and admin staff at the parent unit can see all data, whereas staff located in a department of the hospital can only see data belonging to that specific department.
- SaaS solutions looking to provide admin support for their customers can create a virtual "root" organization. All customers looking for support can make themselves a member of this root organization, which will immediately allow admins of the root organization to see all customer data. Visibility can be turned on and off at will.
Role inheritance requires one additional network request per org level per validated request, so its impact on response time is considerable and should only be used when and where necessary.