403 Unauthorized
. Such checks are declared with AccessPolicy resource.AccessPolicy.link
resource. If AccessPolicy has no links, it's considered as global policy. To authorize a request, Aidbox uses AccessPolicies linked to the current request's User, Client and Operation plus all global policies.true
), the request considered authorized and Aidbox stops further policies evaluation. If all policies denied the request (all of them evaluated to false
), then Aidbox denies such request and responds with 403 Unauthorized
.AccessPolicy.schema
element and this schema will be used to validate the request object. Currently supported JSON Schema version is draft-07.[], {}, "", null
, are removed before passing request into access policy processing.
Make sure to add require
check of the fields that are validated by a json schemarequest.params.resource/type
to be present in a request and have the value "Organization":User.data.practitioner_id
element, the following policy allows requests only to /fhir/Patient/<patient_id>
URLs, and only for those patients who have the Patient.generalPractitioner
element referencing same practitioner as the current User. In other words, User as a Practitioner is only allowed to see patients who are referencing him with the Patient.generalPractitioner
.{{path}}
syntax. For example, to get a role from user {data: {role: 'admin'}}
you can write {{user.data.role}}
. Parameter expressions are escaped by default to protect from SQL injection. If you want to make dynamic queries (parameterize table name, for example), you have to use {{!path}}
syntax. For example, the expression SELECT true from {{!params.resource/type}} limit 1
with params = {resource/type: "Patient"}
will be transformed into SELECT true from "patient".
Such identifier names are double quoted and lower-cased by default.true
regardless the content of the request object.check 1 AND (check 2 OR check 3)
. It's forbidden to have both and
and or
keys on the same level.{x: 1}
matches {x: 1, y: 2 ....}
. This algorithm is recursive — {a: {b: 5}}
matches {a: {b: 5, ...}...}
{request-method: {$enum: ['get','post']}}
matches {request-method: 'post'}
{type: {$contains: {system: 'loinc'}}
matches {type: [{system: 'snomed'}, {system: 'loinc'}]}
{a: {$one-of: [{b: present?}, {c: present?}]}
matches {a: {c: 5}}
parser: {reference: "Patient/pid"} => {id: "pid", resourceType: "Patient"}
{resource: {patient: {$reference: {id: '.user.data.patient_id'}}}
"Patient/pid" => {id: "pid", resourceType: "Patient"}
{params: {subject: {$reference: {id: '.user.data.patient_id'}}}
$not: {status: private}
matches {status: public}
and doesn't match {status: private}.
Be careful using $not
as it is possible to create too permissive policy. See more info below$every: {foo: bar}
matches [{foo: bar}, {foo: bar, baz: quux}]
and doesn't match [{foo: bar}, {foo: baz}]
[1,2]
matches [1,2,3...]
'#'
, it will be transformed into regex and matched as regex. {a: '#\\d+'}
matches {a: '2345'}
'.'
, it's interpreted as a pointer to another path in the subject to compare. For example: {params: {user_id: '.user.id'}}
matches {user: {id: 1}, params: {user_id: 1}},
i.e. user.id == param.user_id
?
{a: 'present?'}
matches {a: 5}
or {a: {b: 6}}
{a: nil?}
matches {b: 6}
$not
as it is possible to create too permissive policy, i.e. statement that something is not allowed means that everything else is allowed. Example:DELETE /Patient/<id>
for unauthorized users.$enum
rpc
field of the AccessPolicy
resource with engine allow-rpc
.