5.5.3. Graph and sub-graph access control

This section explains how to use Cypher to manage privileges for Neo4j role-based access control and fine-grained security.

Privileges control the access rights to graph elements using a combined whitelist/blacklist mechanism. It is possible to grant access, or deny access, or a combination of the two. The user will be able to access the resource if they have a grant (whitelist) and do not have a deny (blacklist) relevant to that resource. All other combinations of GRANT and DENY will result in the matching subgraph being invisible. It will appear to the user as if they have a smaller database (smaller graph).

If a user was not also provided with the database ACCESS privilege then access to the entire database will be denied. Information about the database access privilege can be found in The ACCESS privilege.

5.5.3.1. The GRANT, DENY and REVOKE commands

The GRANT command allows an administrator to grant a privilege to a role in order to access an entity. The DENY command allows an administrator to deny a privilege to a role in order to prevent access to an entity. The REVOKE command allows an administrator to remove a previously granted or denied privilege. The syntax is:

Table 5.31. Privilege command syntax
Command Description
GRANT graph-privilege ON GRAPH[S] {name | *} [entity] TO roles

Grant a privilege to one or multiple roles

DENY graph-privilege ON GRAPH[S] {name | *} [entity] TO roles

Deny a privilege to one or multiple roles

REVOKE GRANT graph-privilege ON GRAPH[S] {name | *} [entity] FROM roles

Revoke a granted privilege from one or multiple roles

REVOKE DENY graph-privilege ON GRAPH[S] {name | *} [entity] FROM roles

Revoke a denied privilege from one or multiple roles

REVOKE graph-privilege ON GRAPH[S] {name | *} [entity] FROM roles

Revoke a granted or denied privilege from one or multiple roles

These commands are almost identical to the database-privileges except for the use of the term GRAPH, the addition of an entity term, and the set of available database-privileges differs from the graph-privileges.

Where the components are:

  • graph-privilege

    • TRAVERSE

      allows the specified entities to be found

    • READ {props}

      allows the specified properties to be read on the found entities. Note that granting property READ access does not imply that the entities with that property can be found. For example if there is also a DENY on it, the entity will not be found. The props can be * which means all properties.

    • MATCH {props}

      this combines both TRAVERSE and READ allowing an entity to be found and its properties read.

    • WRITE

      this privilege can only be assigned to all nodes, relationships and properties in the entire graph (this means that the entity part of the command must also be ELEMENTS * and cannot be more specific).

  • dbname

    • The graph or graphs to associate the privilege with. In {neo4j.version} there can be only one graph per database, and therefor this command uses the database name to refer to that graph. Note that if you delete a database and create a new one with the same name, the new one will NOT have any of the privileges specifically assigned to the deleted graph.
    • Multiple graph names can be specified, comma-separated.
    • It can be * which means all graphs. Any new databases created after this command will also be associated with these privileges.
  • entity

    • The graph elements this privilege applies to:

      • NODES label (nodes with the specified label(s)).
      • RELATIONSHIPS type (relationships of the specific type(s)).
      • ELEMENTS label (both nodes and relationships).
    • The label or type can be * which means all labels or types.
    • Multiple labels or types can be specified, comma-separated.
    • Defaults to ELEMENTS * if omitted.
  • roles

    • The role or roles to associate the privilege with, comma-separated.

It is important to note that using DENY does NOT erase a GRANT command; they both exist. The only way to erase a privilege is with REVOKE.

Figure 5.1. GRANT and DENY Syntax
grant privileges graph

5.5.3.2. Listing privileges

Available privileges for all roles can be seen using SHOW PRIVILEGES.

Query. 

SHOW PRIVILEGES

Lists all privileges for all roles. The table contains columns describing the privilege:

  • access: whether the privilege is granted or denied (whitelist or blacklist)
  • action: which type of privilege this is: access, traverse, read, write, token, schema or admin
  • resource: what type of scope this privilege applies to: the entire dbms, a database, a graph or sub-graph access
  • graph: the specific database or graph this privilege applies to
  • segement: for sub-graph access control, this describes the scope in terms of labels or relationship types
  • role: the role the privilege is granted to
Table 5.32. Result
access action resource graph segment role

41 rows

"GRANTED"

"read"

"all_properties"

"*"

"NODE(*)"

"admin"

"GRANTED"

"write"

"all_properties"

"*"

"NODE(*)"

"admin"

"GRANTED"

"traverse"

"graph"

"*"

"NODE(*)"

"admin"

"GRANTED"

"read"

"all_properties"

"*"

"RELATIONSHIP(*)"

"admin"

"GRANTED"

"write"

"all_properties"

"*"

"RELATIONSHIP(*)"

"admin"

"GRANTED"

"traverse"

"graph"

"*"

"RELATIONSHIP(*)"

"admin"

"GRANTED"

"access"

"database"

"*"

"database"

"admin"

"GRANTED"

"admin"

"database"

"*"

"database"

"admin"

"GRANTED"

"schema"

"database"

"*"

"database"

"admin"

"GRANTED"

"token"

"database"

"*"

"database"

"admin"

"GRANTED"

"read"

"all_properties"

"*"

"NODE(*)"

"architect"

"GRANTED"

"write"

"all_properties"

"*"

"NODE(*)"

"architect"

"GRANTED"

"traverse"

"graph"

"*"

"NODE(*)"

"architect"

"GRANTED"

"read"

"all_properties"

"*"

"RELATIONSHIP(*)"

"architect"

"GRANTED"

"write"

"all_properties"

"*"

"RELATIONSHIP(*)"

"architect"

"GRANTED"

"traverse"

"graph"

"*"

"RELATIONSHIP(*)"

"architect"

"GRANTED"

"access"

"database"

"*"

"database"

"architect"

"GRANTED"

"schema"

"database"

"*"

"database"

"architect"

"GRANTED"

"token"

"database"

"*"

"database"

"architect"

"GRANTED"

"read"

"all_properties"

"*"

"NODE(*)"

"editor"

"GRANTED"

"write"

"all_properties"

"*"

"NODE(*)"

"editor"

"GRANTED"

"traverse"

"graph"

"*"

"NODE(*)"

"editor"

"GRANTED"

"read"

"all_properties"

"*"

"RELATIONSHIP(*)"

"editor"

"GRANTED"

"write"

"all_properties"

"*"

"RELATIONSHIP(*)"

"editor"

"GRANTED"

"traverse"

"graph"

"*"

"RELATIONSHIP(*)"

"editor"

"GRANTED"

"access"

"database"

"*"

"database"

"editor"

"DENIED"

"access"

"database"

"neo4j"

"database"

"noAccessUsers"

"GRANTED"

"read"

"all_properties"

"*"

"NODE(*)"

"publisher"

"GRANTED"

"write"

"all_properties"

"*"

"NODE(*)"

"publisher"

"GRANTED"

"traverse"

"graph"

"*"

"NODE(*)"

"publisher"

"GRANTED"

"read"

"all_properties"

"*"

"RELATIONSHIP(*)"

"publisher"

"GRANTED"

"write"

"all_properties"

"*"

"RELATIONSHIP(*)"

"publisher"

"GRANTED"

"traverse"

"graph"

"*"

"RELATIONSHIP(*)"

"publisher"

"GRANTED"

"access"

"database"

"*"

"database"

"publisher"

"GRANTED"

"token"

"database"

"*"

"database"

"publisher"

"GRANTED"

"read"

"all_properties"

"*"

"NODE(*)"

"reader"

"GRANTED"

"traverse"

"graph"

"*"

"NODE(*)"

"reader"

"GRANTED"

"read"

"all_properties"

"*"

"RELATIONSHIP(*)"

"reader"

"GRANTED"

"traverse"

"graph"

"*"

"RELATIONSHIP(*)"

"reader"

"GRANTED"

"access"

"database"

"*"

"database"

"reader"

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers SHOW PRIVILEGES

Available privileges for a particular role can be seen using SHOW ROLE name PRIVILEGES.

Query. 

SHOW ROLE regularUsers PRIVILEGES

Lists all privileges for role 'regularUsers'

Table 5.33. Result
access action resource graph segment role

1 row

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers SHOW ROLE regularUsers PRIVILEGES

Available privileges for a particular user can be seen using SHOW USER name PRIVILEGES.

Query. 

SHOW USER jake PRIVILEGES

Lists all privileges for user 'jake'

Table 5.34. Result
access action resource graph segment role user

1 row

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

"jake"

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers SHOW USER jake PRIVILEGES

5.5.3.3. The TRAVERSE privilege

Users can be granted the right to find nodes and relationships using the GRANT TRAVERSE privilege.

Command syntax. 

GRANT TRAVERSE
    ON GRAPH[S] {name | *}
        [
           { NODE[S] | RELATIONSHIP[S] | ELEMENT[S] }
           [ { * | labels } ]
        ]
    TO roles

For example, we can allow the user jake, who has role 'regularUsers' to find all nodes with the label Post.

Query. 

GRANT TRAVERSE
ON GRAPH neo4j NODES Post TO regularUsers

0 rows, System updates: 1

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers GRANT TRAVERSE ON GRAPH neo4j NODES Post TO regularUsers

The TRAVERSE privilege can also be denied.

Command syntax. 

DENY TRAVERSE
    ON GRAPH[S] {name | *}
        [
           { NODE[S] | RELATIONSHIP[S] | ELEMENT[S] }
           [ { * | labels } ]
        ]
    TO roles

For example, we can disallow the user jake, who has role 'regularUsers' to find all nodes with the label Payments.

Query. 

DENY TRAVERSE
ON GRAPH neo4j NODES Payments TO regularUsers

0 rows, System updates: 1

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers DENY TRAVERSE ON GRAPH neo4j NODES Payments TO regularUsers

5.5.3.4. The READ privilege

Users can be granted the right to do property reads on nodes and relationships using the GRANT READ privilege. It is very important to note that users can only read properties on entities that they are allowed to find in the first place.

Command syntax. 

GRANT READ
    { * | properties }
    ON GRAPH[S] {name | *}
        [
            { NODE[S] | RELATIONSHIP[S] | ELEMENT[S] }
            [ { * | labels } ]
        ]
    TO roles

For example, we can allow the user jake, who has role 'regularUsers' to read all properties on nodes with the label Post. The * implies that the ability to read all properties also extends to properties that might be added in the future.

Query. 

GRANT READ { * }
ON GRAPH neo4j NODES Post TO regularUsers

0 rows, System updates: 1

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers GRANT READ { * } ON GRAPH neo4j NODES Post TO regularUsers

The READ privilege can also be denied.

Command syntax. 

DENY READ
    { * | properties }
    ON GRAPH[S] {name | *}
        [
            { NODE[S] | RELATIONSHIP[S] | ELEMENT[S] }
            [ { * | labels } ]
        ]
    TO roles

Although we just granted the user 'jake' the right to read all properties, we may want to hide the secret property. The following example shows how to do that.

Query. 

DENY READ { secret }
ON GRAPH neo4j NODES Post TO regularUsers

0 rows, System updates: 1

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers DENY READ { secret } ON GRAPH neo4j NODES Post TO regularUsers

5.5.3.5. The MATCH privilege

As a shorthand for TRAVERSE and READ, users can be granted the right to find and do property reads on nodes and relationships using the GRANT MATCH privilege.

Command syntax. 

GRANT MATCH
    { * | properties }
    ON GRAPH[S] {name | *}
        [
            { NODE[S] | RELATIONSHIP[S] | ELEMENT[S] }
            [ { * | labels } ]
        ]
    TO roles

For example if you want to grant the ability to read the properties language and length for nodes with the label Message, as well as the ability to find these nodes, to a role regularUsers you can use the following GRANT MATCH query.

Query. 

GRANT
MATCH { language, length }
ON GRAPH neo4j NODES Message TO regularUsers

0 rows, System updates: 3

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers GRANT MATCH { language, length } ON GRAPH neo4j NODES Message TO regularUsers

Like all other privileges, the MATCH privilege can also be denied.

Command syntax. 

DENY MATCH
    { * | properties }
    ON GRAPH[S] {name | *}
        [
            { NODE[S] | RELATIONSHIP[S] | ELEMENT[S] }
            [ { * | labels } ]
        ]
    TO roles

Please note that the effect of denying a MATCH privilege depends on whether concrete property keys are specified or a *. If you specify concrete property keys then DENY MATCH will only deny reading those properties. Finding the elements to traverse would still be allowed. If you specify * instead then both traversal of the element and all property reads will be disallowed. The following queries will show examples for this.

Denying to read the property ´content´ on nodes with the label Message for the role regularUsers would look like the following query. Although not being able to read this specific property, nodes with that label can still be traversed (and, depending on other grants, other properties on it could still be read).

Query. 

DENY
MATCH { content }
ON GRAPH neo4j NODES Message TO regularUsers

0 rows, System updates: 1

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers DENY MATCH { content } ON GRAPH neo4j NODES Message TO regularUsers

The following query exemplifies how it would look like if you want to deny both reading all properties and traversing nodes labeled with Account.

Query. 

DENY
MATCH { * }
ON GRAPH neo4j NODES Account TO regularUsers

0 rows, System updates: 2

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers DENY MATCH { * } ON GRAPH neo4j NODES Account TO regularUsers

Please note that REVOKE MATCH is not allowed, instead revoke the individual READ and TRAVERSE privileges.

5.5.3.6. The WRITE privilege

The WRITE privilege can be used to allow the ability to write on a graph. At the moment, granting the WRITE privilege implies that you can do any write operation on any part of the graph.

Command syntax. 

GRANT WRITE
    ON GRAPH[S] {name | *}
    [ ELEMENT[S] * ]
    TO roles

For example, granting the ability to write on the graph neo4j to the role regularUsers would be achieved using:

Query. 

GRANT WRITE
ON GRAPH neo4j TO regularUsers

0 rows, System updates: 2

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers GRANT WRITE ON GRAPH neo4j TO regularUsers

Unlike with GRANT READ it is not possible to restrict WRITE privileges to specific ELEMENTS, NODES or RELATIONSHIPS.

For example, using NODES A will produce a syntax error.

Query. 

GRANT WRITE
ON GRAPH neo4j NODES A TO regularUsers

The use of ELEMENT, NODE or RELATIONSHIP with the WRITE privilege is not supported in this version. (line 1, column 1 (offset: 0)) "GRANT WRITE" ^

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers GRANT WRITE ON GRAPH neo4j NODES A TO regularUsers

The WRITE privilege can also be denied.

Command syntax. 

DENY WRITE
    ON GRAPH[S] {name | *}
    [ ELEMENT[S] * ]
    TO roles

For example, denying the ability to write on the graph neo4j to the role regularUsers would be achieved using:

Query. 

DENY WRITE
ON GRAPH neo4j TO regularUsers

0 rows, System updates: 2

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers DENY WRITE ON GRAPH neo4j TO regularUsers

Users with WRITE privilege but restricted TRAVERSE privileges will not be able to do DETACH DELETE in all cases. See Operations Manual → Fine-grained access control for more info.

5.5.3.7. The REVOKE command

Privileges that were granted or denied earlier can be revoked using the REVOKE command.

Command syntax. 

REVOKE
    [ { GRANT | DENY } ] graph-privilege
    FROM roles

Please note that REVOKE MATCH is not allowed, instead revoke the individual READ and TRAVERSE privileges.

An example usage of the REVOKE command is given here:

Query. 

REVOKE GRANT TRAVERSE
ON GRAPH neo4j NODES Post FROM regularUsers

0 rows

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers REVOKE GRANT TRAVERSE ON GRAPH neo4j NODES Post FROM regularUsers

While it can be explicitly specified that revoke should remove a GRANT or DENY, it is also possible to revoke either one by not specifying at all as the next example demonstrates. Because of this, if there happen to be a GRANT and a DENY on the same privilege, it would remove both.

Query. 

REVOKE TRAVERSE
ON GRAPH neo4j NODES Payments FROM regularUsers

0 rows

Try this query live.  CREATE USER jake SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE CREATE ROLE regularUsers CREATE ROLE noAccessUsers GRANT ROLE regularUsers TO jake GRANT ACCESS ON DATABASE neo4j TO regularUsers DENY ACCESS ON DATABASE neo4j TO noAccessUsers REVOKE TRAVERSE ON GRAPH neo4j NODES Payments FROM regularUsers