Property-based access control

Property-based access control grants permissions to users to read node properties based on property/value conditions. Each property-based privilege can only be restricted by a single property. For information about read privileges and their syntax, see Read privileges.

When using property-based access control, ensure the property used for the rule cannot be modified. Users who can change this property can affect the granted property-based privileges.

Syntax

To specify the property/value conditions of the read privilege, you can use the following syntax:

{GRANT | DENY | REVOKE [GRANT | DENY]}
[IMMUTABLE]
{MATCH | READ | TRAVERSE}
  ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } }
    [
      ELEMENT[S] { * | label-or-rel-type[, ...] }
      | NODE[S] { * | label[, ...] }
      | RELATIONSHIP[S] { * | rel-type[, ...] }
      | FOR {

([var][:label["|" ...]] "{" property: value "}")
  | (var[:label["|" ...]])
      WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } }
  | (var[:label["|" ...]]
WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } )
}

 {TO | FROM} role[, ...]

Performance considerations

Adding property-based access control may lead to a significant performance overhead in certain scenarios. See Limitations for more detailed information.

When having property rules, the following factors can worsen the impact on performance:

  • The number of properties on the nodes concerned (more properties = greater performance impact).

  • The number of property-based privileges (more property-based privileges = greater performance impact).

  • The type of the privilege: TRAVERSE property-based privileges have greater performance impact than READ property-based privileges.

  • The type of storage medium in operation. The impact of the property-based privileges on performance is considerably amplified by accessing disc storage.

To reduce the performance impact, it is recommended to use the block storage format as it is better optimized for the kind of read required for the resolution of property-based privileges.

For performance-critical scenarios, it is recommended to design privileges based on labels.

Examples

You can use the following syntax for defining a property-based privilege:

GRANT privilege-name ON GRAPH graph-name FOR pattern TO role-name

The user role does not need to have READ privilege for the property used by the property-based privilege.

Grant a property-based privilege on a specific property using its value

The following example shows how to grant permission to READ the address property on Email or Website nodes with domain exampledomain.com to role regularUsers:

GRANT READ { address } ON GRAPH * FOR (n:Email|Website) WHERE n.domain = 'exampledomain.com' TO regularUsers

Alternatively, you can use the following syntax:

GRANT READ { address } ON GRAPH * FOR (:Email|Website {domain: 'exampledomain.com'}) TO regularUsers

Grant a property-based privilege using NULL

The following example shows how to grant permission to TRAVERSE nodes with the label Email where property classification is NULL to role regularUsers:

GRANT TRAVERSE ON GRAPH * FOR (n:Email) WHERE n.classification IS NULL TO regularUsers

Deny a property-based privilege using a comparison operator

The following example shows how to deny permission to READ and TRAVERSE nodes where the property classification is different from UNCLASSIFIED to role regularUsers:

DENY MATCH {*} ON GRAPH * FOR (n) WHERE n.classification <> 'UNCLASSIFIED' TO regularUsers

Grant a property-based privilege on all properties using a property value

The following example shows how to grant permission to READ all properties on nodes where the property securityLevel is higher than 3 to role regularUsers:

GRANT READ {*} ON GRAPH * FOR (n) WHERE n.securityLevel > 3 TO regularUsers

The role regularUsers does not need to have READ privilege for the property securityLevel used by the property-based privilege.

Deny a property-based privilege using a list of values

The following example shows how to deny permission to READ all properties on nodes where the property classification is not included in the list of [UNCLASSIFIED, PUBLIC]:

DENY READ {*} ON GRAPH * FOR (n) WHERE NOT n.classification IN ['UNCLASSIFIED', 'PUBLIC'] TO regularUsers

Grant a property-based privilege using temporal value

The following example shows how to grant permission to READ all properties on nodes where the property createdAt is later than the current date:

GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date() TO regularUsers

The date() function is evaluated, and the value used to evaluate the privilege is the date when the property-based privilege is created. Keep this in mind when designing your property rules, and use the SHOW PRIVILEGES AS COMMANDS command to check the stored value. This is essential when revoking property-based privileges containing evaluated function values like date().

You can show the privilege created by the command in the previous example as a revoke command by running:

SHOW ROLE regularUsers PRIVILEGES AS REVOKE COMMANDS
Table 1. Result
command

REVOKE GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt  date('2024-10-25') FROM `regularUsers`

Rows: 1