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 path being inaccessible. What this means in practice depends on whether we are talking about a read privilege or a write privilege.

  • If a entity is not accessible due to read privileges, the data will become invisible to attempts to read it. It will appear to the user as if they have a smaller database (smaller graph).

  • If an entity is not accessible due to write privileges, an error will occur on any attempt to write that data.

In this document we will often use the terms 'allows' and 'enables' in seemingly identical ways. However, there is a subtle difference. We will use 'enables' to refer to the consequences of read privileges where a restriction will not cause an error, only a reduction in the apparent graph size. We will use 'allows' to refer to the consequence of write privileges where a restriction can result in an error.

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.

1. The GRANT, DENY and REVOKE commands

The administrators can use Cypher commands to manage Neo4j graph administrative rights. The components of the graph privilege commands are:

  • the command:

    • GRANT – gives privileges to roles.

    • DENY – denies privileges to roles.

    • REVOKE – removes granted or denied privilege from roles.

  • graph-privilege

  • name

    • The graph or graphs to associate the privilege with. Because in Neo4j 4.2 you can have only one graph per database, this command uses the database name to refer to that graph.

      If you delete a database and create a new one with the same name, the new one will NOT have the privileges assigned to the deleted graph.

    • It can be * which means all graphs. Graphs created after this command execution 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.

    • Some of the commands for write privileges do not allow an entity part, see Write privileges for details.

  • role[, …​]

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

Table 1. General graph privilege command syntax
Command Description
GRANT graph-privilege ON {DEFAULT GRAPH | GRAPH[S] {* | name[, ...]}} [entity] TO role[, ...]

Grant a privilege to one or multiple roles.

DENY graph-privilege ON {DEFAULT GRAPH | GRAPH[S] {* | name[, ...]}} [entity] TO role[, ...]

Deny a privilege to one or multiple roles.

REVOKE GRANT graph-privilege ON {DEFAULT GRAPH | GRAPH[S] {* | name[, ...]}} [entity] FROM role[, ...]

Revoke a granted privilege from one or multiple roles.

REVOKE DENY graph-privilege ON {DEFAULT GRAPH | GRAPH[S] {* | name[, ...]}} [entity] FROM role[, ...]

Revoke a denied privilege from one or multiple roles.

REVOKE graph-privilege ON {DEFAULT GRAPH | GRAPH[S] {* | name[, ...]}} [entity] FROM role[, ...]

Revoke a granted or denied privilege from one or multiple roles.

DENY does NOT erase a granted privilege; they both exist. Use REVOKE if you want to remove a privilege.

The general grant and deny syntax is illustrated in the image below.

grant privileges overview
Figure 1. GRANT and DENY Syntax

A more detailed syntax illustration would be the image below for graph privileges.

grant privileges graph
Figure 2. Syntax of GRANT and DENY Graph Privileges. The { and } are part of the syntax and not used for grouping.

The below image shows the hierarchy between the different graph privileges.

privilege hierarchy graph
Figure 3. Graph privileges hierarchy

2. Listing privileges

Available privileges can be displayed using the different SHOW PRIVILEGES commands.

Table 2. Show privileges command syntax
Command Description
SHOW [ALL] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    [YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
    [WHERE expression]
    [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]

List all privileges.

SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    [YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
    [WHERE expression]
    [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]

List privileges for a specific role.

SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    [YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
    [WHERE expression]
    [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]

List privileges for a specific user, or the current user.

When using the RETURN clause, the YIELD clause is mandatory and may not be omitted.

2.1. Examples for listing all privileges

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

Command syntax
SHOW [ALL] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    [WHERE expression]

SHOW [ALL] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]
    [WHERE expression]
    [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
Query
SHOW PRIVILEGES

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

  • access: whether the privilege is granted or denied

  • action: which type of privilege this is: traverse, read, match, write, a database privilege, a dbms privilege 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

  • segment: 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 3. Result
access action resource graph segment role

"GRANTED"

"execute"

"database"

"*"

"FUNCTION(*)"

"PUBLIC"

"GRANTED"

"execute"

"database"

"*"

"PROCEDURE(*)"

"PUBLIC"

"GRANTED"

"access"

"database"

"DEFAULT"

"database"

"PUBLIC"

"GRANTED"

"match"

"all_properties"

"*"

"NODE(*)"

"admin"

"GRANTED"

"write"

"graph"

"*"

"NODE(*)"

"admin"

"GRANTED"

"match"

"all_properties"

"*"

"RELATIONSHIP(*)"

"admin"

"GRANTED"

"write"

"graph"

"*"

"RELATIONSHIP(*)"

"admin"

"GRANTED"

"access"

"database"

"*"

"database"

"admin"

"GRANTED"

"admin"

"database"

"*"

"database"

"admin"

"GRANTED"

"constraint"

"database"

"*"

"database"

"admin"

"GRANTED"

"index"

"database"

"*"

"database"

"admin"

"GRANTED"

"token"

"database"

"*"

"database"

"admin"

"GRANTED"

"match"

"all_properties"

"*"

"NODE(*)"

"architect"

"GRANTED"

"write"

"graph"

"*"

"NODE(*)"

"architect"

"GRANTED"

"match"

"all_properties"

"*"

"RELATIONSHIP(*)"

"architect"

"GRANTED"

"write"

"graph"

"*"

"RELATIONSHIP(*)"

"architect"

"GRANTED"

"access"

"database"

"*"

"database"

"architect"

"GRANTED"

"constraint"

"database"

"*"

"database"

"architect"

"GRANTED"

"index"

"database"

"*"

"database"

"architect"

"GRANTED"

"token"

"database"

"*"

"database"

"architect"

"GRANTED"

"match"

"all_properties"

"*"

"NODE(*)"

"editor"

"GRANTED"

"write"

"graph"

"*"

"NODE(*)"

"editor"

"GRANTED"

"match"

"all_properties"

"*"

"RELATIONSHIP(*)"

"editor"

"GRANTED"

"write"

"graph"

"*"

"RELATIONSHIP(*)"

"editor"

"GRANTED"

"access"

"database"

"*"

"database"

"editor"

"DENIED"

"access"

"database"

"neo4j"

"database"

"noAccessUsers"

"GRANTED"

"match"

"all_properties"

"*"

"NODE(*)"

"publisher"

"GRANTED"

"write"

"graph"

"*"

"NODE(*)"

"publisher"

"GRANTED"

"match"

"all_properties"

"*"

"RELATIONSHIP(*)"

"publisher"

"GRANTED"

"write"

"graph"

"*"

"RELATIONSHIP(*)"

"publisher"

"GRANTED"

"access"

"database"

"*"

"database"

"publisher"

"GRANTED"

"token"

"database"

"*"

"database"

"publisher"

"GRANTED"

"match"

"all_properties"

"*"

"NODE(*)"

"reader"

"GRANTED"

"match"

"all_properties"

"*"

"RELATIONSHIP(*)"

"reader"

"GRANTED"

"access"

"database"

"*"

"database"

"reader"

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

Rows: 36

It is also possible to filter and sort the results by using YIELD, ORDER BY and WHERE.

Query
SHOW PRIVILEGES YIELD role, access, action, segment ORDER BY action WHERE role = 'admin'

In this example:

  • The number of columns returned has been reduced with the YIELD clause.

  • The order of the returned columns has been changed.

  • The results have been filtered to only return the admin role using a WHERE clause.

  • The results are ordered by the action column using ORDER BY.

SKIP and LIMIT can also be used to paginate the results.

Table 4. Result
role access action segment

"admin"

"GRANTED"

"access"

"database"

"admin"

"GRANTED"

"admin"

"database"

"admin"

"GRANTED"

"constraint"

"database"

"admin"

"GRANTED"

"index"

"database"

"admin"

"GRANTED"

"match"

"NODE(*)"

"admin"

"GRANTED"

"match"

"RELATIONSHIP(*)"

"admin"

"GRANTED"

"token"

"database"

"admin"

"GRANTED"

"write"

"NODE(*)"

"admin"

"GRANTED"

"write"

"RELATIONSHIP(*)"

Rows: 9

WHERE can be used without YIELD

Query
SHOW PRIVILEGES WHERE graph <> '*'

In this example, the WHERE clause is used to filter privileges down to those that target specific graphs only.

Table 5. Result
access action graph resource role segment

"GRANTED"

"access"

"DEFAULT"

"database"

"PUBLIC"

"database"

"DENIED"

"access"

"neo4j"

"database"

"noAccessUsers"

"database"

"GRANTED"

"access"

"neo4j"

"database"

"regularUsers"

"database"

Rows: 3

Aggregations in the RETURN clause can be used to group privileges. In this case, by user and granted / denied.

Query
SHOW PRIVILEGES YIELD * RETURN role, access, collect([graph, resource, segment, action]) as privileges
Table 6. Result
role access privileges

"PUBLIC"

"GRANTED"

[["*","database","FUNCTION(*)","execute"],["*","database","PROCEDURE(*)","execute"],["DEFAULT","database","database","access"]]

"admin"

"GRANTED"

[["*","all_properties","NODE(*)","match"],["*","graph","NODE(*)","write"],["*","all_properties","RELATIONSHIP(*)","match"],["*","graph","RELATIONSHIP(*)","write"],["*","database","database","access"],["*","database","database","admin"],["*","database","database","constraint"],["*","database","database","index"],["*","database","database","token"]]

"architect"

"GRANTED"

[["*","all_properties","NODE(*)","match"],["*","graph","NODE(*)","write"],["*","all_properties","RELATIONSHIP(*)","match"],["*","graph","RELATIONSHIP(*)","write"],["*","database","database","access"],["*","database","database","constraint"],["*","database","database","index"],["*","database","database","token"]]

"editor"

"GRANTED"

[["*","all_properties","NODE(*)","match"],["*","graph","NODE(*)","write"],["*","all_properties","RELATIONSHIP(*)","match"],["*","graph","RELATIONSHIP(*)","write"],["*","database","database","access"]]

"noAccessUsers"

"DENIED"

[["neo4j","database","database","access"]]

"publisher"

"GRANTED"

[["*","all_properties","NODE(*)","match"],["*","graph","NODE(*)","write"],["*","all_properties","RELATIONSHIP(*)","match"],["*","graph","RELATIONSHIP(*)","write"],["*","database","database","access"],["*","database","database","token"]]

"reader"

"GRANTED"

[["*","all_properties","NODE(*)","match"],["*","all_properties","RELATIONSHIP(*)","match"],["*","database","database","access"]]

"regularUsers"

"GRANTED"

[["neo4j","database","database","access"]]

Rows: 8

The RETURN clause can also be used to order and paginate the results, which is useful when combined with YIELD and WHERE. In this example the query returns privileges for display five-per-page, and skips the first five to display the second page.

Query
SHOW PRIVILEGES YIELD * RETURN * ORDER BY role SKIP 5 LIMIT 5
Table 7. Result
access action graph resource role segment

"GRANTED"

"match"

"*"

"all_properties"

"admin"

"RELATIONSHIP(*)"

"GRANTED"

"write"

"*"

"graph"

"admin"

"RELATIONSHIP(*)"

"GRANTED"

"access"

"*"

"database"

"admin"

"database"

"GRANTED"

"admin"

"*"

"database"

"admin"

"database"

"GRANTED"

"constraint"

"*"

"database"

"admin"

"database"

Rows: 5

2.2. Examples for listing privileges for specific roles

Available privileges for specific roles can be displayed using SHOW ROLE name PRIVILEGES.

Command syntax
SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    [WHERE expression]

SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]
    [WHERE expression]
    [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
Query
SHOW ROLE regularUsers PRIVILEGES

Lists all privileges for role regularUsers.

Table 8. Result
access action resource graph segment role

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

Rows: 1

Query
SHOW ROLES regularUsers, noAccessUsers PRIVILEGES

Lists all privileges for roles regularUsers and noAccessUsers.

Table 9. Result
access action resource graph segment role

"DENIED"

"access"

"database"

"neo4j"

"database"

"noAccessUsers"

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

Rows: 2

Available privileges for roles can also be output as Cypher commands with the optional AS COMMAND[S].

Query
SHOW ROLE admin PRIVILEGES AS COMMANDS
Table 10. Result
command

"GRANT ACCESS ON DATABASE * TO `admin`"

"GRANT ALL DBMS PRIVILEGES ON DBMS TO `admin`"

"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `admin`"

"GRANT INDEX MANAGEMENT ON DATABASE * TO `admin`"

"GRANT MATCH {*} ON GRAPH * NODE * TO `admin`"

"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `admin`"

"GRANT NAME MANAGEMENT ON DATABASE * TO `admin`"

"GRANT START ON DATABASE * TO `admin`"

"GRANT STOP ON DATABASE * TO `admin`"

"GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO `admin`"

"GRANT WRITE ON GRAPH * TO `admin`"

Rows: 11

Like other SHOW commands, the output can also be processed using YIELD / WHERE / RETURN.

Query
SHOW ROLE architect PRIVILEGES AS COMMANDS WHERE command CONTAINS 'MATCH'
Table 11. Result
command

"GRANT MATCH {*} ON GRAPH * NODE * TO `architect`"

"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `architect`"

Rows: 2

It is also possible to have privileges output as revoke commands. For more on revoke commands, please see The REVOKE command.

Query
SHOW ROLE reader PRIVILEGES AS REVOKE COMMANDS
Table 12. Result
command

"REVOKE GRANT ACCESS ON DATABASE * FROM `reader`"

"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `reader`"

"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `reader`"

Rows: 3

2.3. Examples for listing privileges for specific users

Available privileges for specific users can be displayed using SHOW USER name PRIVILEGES.

Please note that if a non-native auth provider like LDAP is in use, SHOW USER PRIVILEGES will only work in a limited capacity; It is only possible for a user to show their own privileges. Other users' privileges cannot be listed when using a non-native auth provider.

Command syntax
SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    [WHERE expression]

SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]]
    YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]
    [WHERE expression]
    [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]
Query
SHOW USER jake PRIVILEGES

Lists all privileges for user jake.

Table 13. Result
access action resource graph segment role user

"GRANTED"

"execute"

"database"

"*"

"FUNCTION(*)"

"PUBLIC"

"jake"

"GRANTED"

"execute"

"database"

"*"

"PROCEDURE(*)"

"PUBLIC"

"jake"

"GRANTED"

"access"

"database"

"DEFAULT"

"database"

"PUBLIC"

"jake"

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

"jake"

Rows: 4

Query
SHOW USERS jake, joe PRIVILEGES

Lists all privileges for users jake and joe.

Table 14. Result
access action resource graph segment role user

"GRANTED"

"execute"

"database"

"*"

"FUNCTION(*)"

"PUBLIC"

"jake"

"GRANTED"

"execute"

"database"

"*"

"PROCEDURE(*)"

"PUBLIC"

"jake"

"GRANTED"

"access"

"database"

"DEFAULT"

"database"

"PUBLIC"

"jake"

"GRANTED"

"access"

"database"

"neo4j"

"database"

"regularUsers"

"jake"

"GRANTED"

"execute"

"database"

"*"

"FUNCTION(*)"

"PUBLIC"

"joe"

"GRANTED"

"execute"

"database"

"*"

"PROCEDURE(*)"

"PUBLIC"

"joe"

"GRANTED"

"access"

"database"

"DEFAULT"

"database"

"PUBLIC"

"joe"

"DENIED"

"access"

"database"

"neo4j"

"database"

"noAccessUsers"

"joe"

Rows: 8

The same command can be used at all times to review available privileges for the current user. For this purpose, a shorter form of the the command also exists: SHOW USER PRIVILEGES.

Query
SHOW USER PRIVILEGES

Available privileges for users can also be output as Cypher commands with the optional AS COMMAND[S].

When showing user privileges as commands, the roles in the Cypher commands are replaced with a parameter. This can be used to quickly create new roles based on the privileges of specific users.

Query
SHOW USER jake PRIVILEGES AS COMMANDS
Table 15. Result
command

"GRANT ACCESS ON DATABASE `neo4j` TO $role"

"GRANT ACCESS ON DEFAULT DATABASE TO $role"

"GRANT EXECUTE FUNCTION * ON DBMS TO $role"

"GRANT EXECUTE PROCEDURE * ON DBMS TO $role"

Rows: 4

Like other SHOW commands, the output can also be processed using YIELD / WHERE / RETURN. Additionally, just as with role privileges, it is also possible to show user privileges as revoke commands.

Query
SHOW USER jake PRIVILEGES AS REVOKE COMMANDS WHERE command CONTAINS 'EXECUTE'
Table 16. Result
command

"REVOKE GRANT EXECUTE FUNCTION * ON DBMS FROM $role"

"REVOKE GRANT EXECUTE PROCEDURE * ON DBMS FROM $role"

Rows: 2

3. 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 role[, ...]

An example usage of the REVOKE command is given here:

Query
REVOKE GRANT TRAVERSE ON DEFAULT GRAPH NODES Post FROM regularUsers

0 rows, System updates: 1

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 DEFAULT GRAPH NODES Payments FROM regularUsers

0 rows, System updates: 2