From fa639137f8a50aa9b0de82c8113de39d201a522c Mon Sep 17 00:00:00 2001 From: Darrell Warde Date: Wed, 7 Aug 2024 13:44:17 +0100 Subject: [PATCH 1/3] Add documentation for `@subscriptionsAuthorization` --- modules/ROOT/pages/directives/index.adoc | 2 +- .../ROOT/pages/security/authorization.adoc | 6 ++ modules/ROOT/pages/security/index.adoc | 1 + .../security/subscriptions-authorization.adoc | 64 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 modules/ROOT/pages/security/subscriptions-authorization.adoc diff --git a/modules/ROOT/pages/directives/index.adoc b/modules/ROOT/pages/directives/index.adoc index 0fcab321..a8929ad3 100644 --- a/modules/ROOT/pages/directives/index.adoc +++ b/modules/ROOT/pages/directives/index.adoc @@ -47,7 +47,7 @@ a| Required to differentiate interfaces that are used for relationship propertie | Used in combination with `@jwt`. Configures the JWT authentication and authorization filters to include an additional JWT claim which is either nested or using special characters not supported by GraphQL. -| `@subscriptionsAuthorization` +| xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] | Specifies authorization rules for subscriptions on the type. |=== diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index 91e2b11f..20c422a6 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -10,6 +10,12 @@ All authorization rules have an implied requirement for authentication, given th In the case of explicit authentication, configured using the `@authentication` directive, it is only ever evaluated during Cypher translation time. Unauthenticated requests with queries requiring authentication never reach the database. +[WARNING] +==== +The `@authorization` directive does apply to subscriptions, it only applies to queries and mutations. +You should configure authorization for subscriptions using xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] if you intend to use subscriptions in your API and want the events protected. +==== + == Rules === Filtering diff --git a/modules/ROOT/pages/security/index.adoc b/modules/ROOT/pages/security/index.adoc index e20dfd70..49603558 100644 --- a/modules/ROOT/pages/security/index.adoc +++ b/modules/ROOT/pages/security/index.adoc @@ -8,6 +8,7 @@ auth/authorization/where.adoc, authentication-and-authorization/index.adoc * xref::/security/authentication.adoc[Authentication] - Explicit authentication, configured using the `@authentication` directive. * xref::/security/authorization.adoc[Authorization] - Authorization rules set using the `@authorization` directive. +* xref::/security/subscriptions-authorization.adoc[Subscriptions authorization] - Authorization rules for subscriptions set using the `@subscriptionsAuthorization` directive. * xref::/security/configuration.adoc[Configuration] - Instructions to set up instantiation. * xref::/security/impersonation-and-user-switching.adoc[Impersonation and user switching] - How to set up impersonation and user switching features. * xref::/security/operations.adoc[Operations] - Reference on GraphQL queries and how each location in each query triggers the evaluation of different authentication/authorization rules. diff --git a/modules/ROOT/pages/security/subscriptions-authorization.adoc b/modules/ROOT/pages/security/subscriptions-authorization.adoc new file mode 100644 index 00000000..09e61852 --- /dev/null +++ b/modules/ROOT/pages/security/subscriptions-authorization.adoc @@ -0,0 +1,64 @@ +[[subscriptions-authorization]] +:description: This page describes how to set up authorization features for subscriptions in the Neo4j GraphQL Library. += Subscriptions authorization + +Subscriptions require their own authorization rules, which are configured with the `@subscriptionsAuthorization` directive. These rules are different to normal authorization rules because only filtering rules are available for subscriptions events and subscriptions events have more limitations in how they can be filtered. + +All subscriptions authorization rules have an implied requirement for authentication, given that the rules are normally evaluated against values in the JWT payload. + +== Rules + +=== Filtering + +Filtering rules will prevent events which contain information that users don't have access to from ever reaching them - they will receive no indication that this is the case. +These rules are evaluated when the events are returned from the database, before they are broadcasted out to subscribing GraphQL clients. + +For instance, here is how to filter out `User` events which don't match the JWT of the user listening for events: + +[source, graphql, indent=0] +---- +type User @subscriptionsAuthorization(filter: [ + { where: { node: { id: "$jwt.sub" } } } +]) { + id: ID! +} +---- + +==== Events + +Filtering can be configured to only be performed on certain events: + +* `CREATED` +* `UPDATED` +* `DELETED` +* `RELATIONSHIP_CREATED` +* `RELATIONSHIP_DELETED` + +For instance, to only require filtering for mutations to a type itself and not its relationships: + +[source, graphql, indent=0] +---- +type User @subscriptionsAuthorization(filter: [ + { events: [CREATED, UPDATED, DELETED], where: { node: { id: "$jwt.sub" } } } +]) { + id: ID! +} +---- + +== Authorization without authentication + +Authentication is implicitly required for every authorization check by default, but this can be disabled on a per-rule basis. +This could be the case, for instance, when a node has a property which flags whether the node should be public or not. + +For instance, in the case where some `Post` nodes are private whilst other `Post` nodes are public, here is how to set this up: + +[source, graphql, indent=0] +---- +type Post @subscriptionsAuthorization(filter: [ + { requireAuthentication: false, where: { node: { public: true } } } +]) { + title: String! + content: String! + public: Boolean! +} +---- \ No newline at end of file From 68b84634de3dd58fa316cf03307ad2d0accc5ea8 Mon Sep 17 00:00:00 2001 From: Darrell Warde <8117355+darrellwarde@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:48:26 +0100 Subject: [PATCH 2/3] Update modules/ROOT/pages/security/authorization.adoc Co-authored-by: Michael Webb <28074382+mjfwebb@users.noreply.github.com> --- modules/ROOT/pages/security/authorization.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index 20c422a6..485dd1da 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -12,7 +12,7 @@ Unauthenticated requests with queries requiring authentication never reach the d [WARNING] ==== -The `@authorization` directive does apply to subscriptions, it only applies to queries and mutations. +The `@authorization` directive does not apply to subscriptions, it only applies to queries and mutations. You should configure authorization for subscriptions using xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] if you intend to use subscriptions in your API and want the events protected. ==== From 17153e3a953836f59e2105456a9c5da9b0340491 Mon Sep 17 00:00:00 2001 From: Darrell Warde <8117355+darrellwarde@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:13:56 +0100 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> --- modules/ROOT/pages/security/authorization.adoc | 2 +- modules/ROOT/pages/security/subscriptions-authorization.adoc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index 485dd1da..adb5aa1b 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -13,7 +13,7 @@ Unauthenticated requests with queries requiring authentication never reach the d [WARNING] ==== The `@authorization` directive does not apply to subscriptions, it only applies to queries and mutations. -You should configure authorization for subscriptions using xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] if you intend to use subscriptions in your API and want the events protected. +Instead, use xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] to configure the authorization for subscriptions if you intend to use subscriptions in your API and want the events protected. ==== == Rules diff --git a/modules/ROOT/pages/security/subscriptions-authorization.adoc b/modules/ROOT/pages/security/subscriptions-authorization.adoc index 09e61852..cb0490f2 100644 --- a/modules/ROOT/pages/security/subscriptions-authorization.adoc +++ b/modules/ROOT/pages/security/subscriptions-authorization.adoc @@ -2,7 +2,8 @@ :description: This page describes how to set up authorization features for subscriptions in the Neo4j GraphQL Library. = Subscriptions authorization -Subscriptions require their own authorization rules, which are configured with the `@subscriptionsAuthorization` directive. These rules are different to normal authorization rules because only filtering rules are available for subscriptions events and subscriptions events have more limitations in how they can be filtered. +Subscriptions require their own authorization rules, which are configured with the `@subscriptionsAuthorization` directive. +These rules are different to normal authorization rules because only filtering rules are available for subscriptions events and subscriptions events have more limitations in how they can be filtered. All subscriptions authorization rules have an implied requirement for authentication, given that the rules are normally evaluated against values in the JWT payload. @@ -10,7 +11,7 @@ All subscriptions authorization rules have an implied requirement for authentica === Filtering -Filtering rules will prevent events which contain information that users don't have access to from ever reaching them - they will receive no indication that this is the case. +Filtering rules prevent events which contain information that users don't have access to from reaching them - they will receive no indication that this is the case. These rules are evaluated when the events are returned from the database, before they are broadcasted out to subscribing GraphQL clients. For instance, here is how to filter out `User` events which don't match the JWT of the user listening for events: