Access Control Model
ESUS uses Attribute-Based Access Control (ABAC) — every protected route evaluates the requesting user’s roles and permissions before allowing access. For PHI resources, an additional patient consent check is performed.
How It Works
Every FHIR endpoint is protected by the guardResource middleware, which:
- Maps the HTTP method to a FHIR action (
GET → read,POST → create,PUT/PATCH → update,DELETE → delete) - Checks the user’s roles and permissions against the requested resource and action
- For PHI resources (Patient, Encounter, Observation, Condition, etc.) on specific ID reads/updates/deletes: checks the
Consenttable for active consent - Returns a FHIR
OperationOutcomewith403 Forbiddenon denial
Roles
| Role | Description |
|---|---|
admin | Full system access — all resources, all actions |
practitioner | Clinical access — read/write for assigned patient resources |
patient | Self-service — read/write only their own records |
researcher | Read-only access to de-identified data |
api-client | Scoped access based on API key scopes |
emergency-responder | Emergency override access (fully audited) |
Managing Roles
# List all roles in your organization
curl https://api.esus.health/roles \
-H "Authorization: Bearer TOKEN"
# Create a custom role
curl -X POST https://api.esus.health/roles \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "lab-technician",
"permissions": [
{ "resource": "Observation", "action": "create" },
{ "resource": "Observation", "action": "read" },
{ "resource": "DiagnosticReport", "action": "create" },
{ "resource": "DiagnosticReport", "action": "read" },
{ "resource": "Specimen", "action": "read" }
]
}'
Assigning Roles to Users
# Assign a role to a user
curl -X POST https://api.esus.health/roles/users/:userId/assign \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{ "roleId": "b8c2d3e4-f5a6-7890-bcde-f01234567890" }'
# Remove a role from a user
curl -X DELETE https://api.esus.health/roles/users/:userId/:roleId \
-H "Authorization: Bearer TOKEN"
Viewing Available Permissions
curl https://api.esus.health/roles/permissions \
-H "Authorization: Bearer TOKEN"
Response:
[
{ "resource": "Patient", "action": "read" },
{ "resource": "Patient", "action": "create" },
{ "resource": "Patient", "action": "update" },
{ "resource": "Patient", "action": "delete" },
{ "resource": "Observation", "action": "read" },
...
]
API Key Scopes
When using API keys, access is controlled by scopes defined at key creation time. Scopes follow the Resource.action pattern and map directly to permissions:
| Scope | Grants |
|---|---|
Patient.read | Read Patient resources |
Patient.write | Create/update/delete Patients |
Observation.* | All Observation operations |
*.read | Read all resources |
* | Full access (use with care) |
Emergency Override
For emergency situations, users with the admin or emergency-responder role can bypass normal access controls using the X-Emergency-Override header:
curl https://api.esus.health/fhir/Patient/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
-H "Authorization: Bearer TOKEN" \
-H "X-Emergency-Override: true"
Important: All emergency override accesses are:
- Immediately written to the audit log
- Flagged with
emergencyOverride: truein the audit entry - Subject to post-access review by administrators
Attempting to use this header without the appropriate role returns 403 Forbidden.
Consent-Gated Access
For PHI resources, the ABAC engine also checks whether an active Consent record exists for the patient. If the patient has revoked consent for a particular practitioner or organization, access is denied even if the user has the correct role.
See Patient Consent for how to create and manage consent records.