Access Control
Haste Health implements fine-grained access control using AccessPolicyV2 resources. These policies provide attribute-based access control (ABAC) beyond basic OAuth scopes, enabling complex authorization rules based on user identity, resource properties, and request context.
AccessPolicyV2 Resource
AccessPolicyV2 resources define authorization policies that evaluate against API requests to determine access permissions.
Key Fields
- engine: Evaluation engine (
full-access,rule-engine) - target.link: Reference to User or Membership this policy applies to
- rule: Array of authorization rules with actions, resources, and conditions
- name: Human-readable policy description
Policy Engines
AccessPolicyV2 supports multiple evaluation engines for different authorization models:
Full Access Engine
Engine code: full-access
Grants unrestricted access to all resources and operations. The simplest engine—always returns success.
Use cases:
- System administrators with full platform access
- Automated service accounts needing complete access
- Development/testing environments
Example:
{
"resourceType": "AccessPolicyV2",
"name": "Admin Full Access",
"engine": "full-access",
"target": {
"link": {
"reference": "Membership/admin-membership"
}
}
}
Rule Engine
Engine code: rule-engine
Enables fine-grained, attribute-based access control using FHIRPath expressions to define rules and conditions.
Special Variables:
The following special variables are available within FHIRPath expressions for rules and conditions:
user: The authenticated user this includes the user's id.request: The incoming API request details, including method and resource type.level: Whether request is at 'instance', 'type' or 'system' level.type: One of "create"|"read"|"vread"|"update"|"patch"|"delete"|"capabilities"|"search"|"history"|"invoke"|"batch"|"transaction"|"compartment"resourceType: The FHIR resource type being accessed (if applicable).resource: The FHIR resource if present in the request IE (create).id: The resource ID if applicable.parameters: The search parameters if applicable.
Attributes
Attributes are how you can make pull in external data during a policy evaluation. We support 'read', and 'search' operations.
For example
"attribute": [
{
"operation": {
"type": "read",
"path": {
"language": "text/fhirpath",
"expression": "Patient/123"
}
},
"attributeId": "patient"
}
]
This operation will read the Patient with ID 123 and make it available in FHIRPath expressions as %patient.
Rules
Rules define whether or not to permit or deny access based on conditions. Each rule includes:
- effect:
permitordeny - combineBehavior:
all(AND) orany(OR) - target.expression: FHIRPath expression to determine whether or not to evaluate this rule
- condition.expression: FHIRPath expression evaluated if target matches
Example:
{
"resourceType": "AccessPolicyV2",
"name": "Rule Engine",
"engine": "rule-engine",
"rule": [
{
"name": "Access Control",
"combineBehavior": "any",
"rule": [
{
"name": "Is Read request",
"target": {
"expression": {
"language": "text/fhirpath",
"expression": "true"
}
},
"condition": {
"expression": {
"language": "text/fhirpath",
"expression": "%request.type = 'read'"
}
}
}
]
}
]
}
Policy Evaluation
When a user makes an API request:
- Token validation: JWT token verified and claims extracted
- Policy loading: AccessPolicyV2 resources loaded by version IDs in token
- Engine execution: Each policy evaluated using its specified engine
- Decision: If any policy grants access, request proceeds; otherwise denied
Multiple policies can apply to a single user (via Membership). The system uses an "any allow" model—if any policy permits the action, it's allowed.
Associating Policies with Users
Policies link to resources via the target.link field.
{
"resourceType": "Membership",
"link": {
"reference": "User/user-789"
},
"role": "member"
}
Then reference the Membership in the policy:
{
"resourceType": "AccessPolicyV2",
"target": {
"link": {
"reference": "Membership/membership-id"
}
}
}
During authentication, the system:
- Finds user's Memberships
- Searches for AccessPolicyV2 where
target.linkreferences those Memberships - Includes policy version IDs in access token
Best Practices
Principle of least privilege: Grant minimum necessary permissions
- Start with restrictive policies
- Add specific exceptions as needed
Layer policies: Combine multiple policies for flexibility
- Base policy for common permissions
- Specific policies for exceptional access
Test thoroughly: Validate policies before production
- Use
$evaluate-policyoperation - Test edge cases and negative scenarios
Document conditions: Use clear policy names and document complex FHIRPath expressions
Version carefully: Policies are versioned—understand token caching implications
Related Documentation
- Membership: Link policies to users
- Scopes: OAuth scope-based permissions
- AccessPolicyV2: Resource overview
- AccessPolicyV2 Schema: Complete resource reference