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:

  1. Maps the HTTP method to a FHIR action (GET → read, POST → create, PUT/PATCH → update, DELETE → delete)
  2. Checks the user’s roles and permissions against the requested resource and action
  3. For PHI resources (Patient, Encounter, Observation, Condition, etc.) on specific ID reads/updates/deletes: checks the Consent table for active consent
  4. Returns a FHIR OperationOutcome with 403 Forbidden on denial

Roles

RoleDescription
adminFull system access — all resources, all actions
practitionerClinical access — read/write for assigned patient resources
patientSelf-service — read/write only their own records
researcherRead-only access to de-identified data
api-clientScoped access based on API key scopes
emergency-responderEmergency 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:

ScopeGrants
Patient.readRead Patient resources
Patient.writeCreate/update/delete Patients
Observation.*All Observation operations
*.readRead 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: true in the audit entry
  • Subject to post-access review by administrators

Attempting to use this header without the appropriate role returns 403 Forbidden.

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.