Skip to content

Conversation

@rsill-neo4j
Copy link
Contributor

@rsill-neo4j rsill-neo4j commented Sep 22, 2025

this PR is kinda dependent on #274 now
would be good to publish them simultaneously
274 has two js examples missing

@rsill-neo4j rsill-neo4j requested a review from mjfwebb September 22, 2025 12:05
@luffy1727 luffy1727 marked this pull request as draft October 21, 2025 12:08
@rsill-neo4j rsill-neo4j marked this pull request as ready for review October 24, 2025 08:22
@neo4j-docops-agent
Copy link
Collaborator

This PR includes documentation updates
View the updated docs at https://neo4j-docs-graphql-280.surge.sh

New pages:

Copy link

@keremgocen keremgocen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's looking good so far and has valuable information. However there are a few typos and I think we can make it more practical with some code examples. I left a few comments.


For the same reason it is advisable to avoid introspection and data field suggestions, it can make your API more secure to catch internal errors and redact which information you want to pass on to the end user.

For example, the following error reveals information XY:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this also a placeholder XY? feels like the JSON example here could be more illustrative?


[source, graphql, indent=0]
----
// example

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing example here I think?

There are many ways and places to use timeouts.
Here are a few examples.

// examples

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing example?


Follow the input validation methods summarized in the link:https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html#input-validation[OWASP Cheat Sheet Series].

// Examples?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also here, do we want an actual example?

----
import depthLimit from 'graphql-depth-limit'
import express from 'express'
import graphqlHTTP from 'express-graphql'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we maybe use a more up to date example here? we could replace the deprecated express-graphql with graphql-http, apparently. (cc: @mjfwebb)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll replace this example with an example using GraphQL Armor

Comment on lines 408 to 464
Returning large query result lists can negatively affect server performance.
For example, a query like the following would return a siginificant number of nodes:

[source, graphql, indent=0]
----
query {
order(first: 1000) {
orderID
products(last: 100) {
productName
productCategory
}
}
}
----

To avoid this, you can cap the input number directly in your resolvers, for example like this:

[source, graphql, indent=0]
----
// example
----

Alternatively, use a library such as link:https://github.com/joonhocho/graphql-input-number[graphql-input-number]:

[source, typescript, indent=0]
----
import {
GraphQLInputInt,
GraphQLInputFloat,
} from 'graphql-input-number';
const argType = GraphQLInputInt({
name: 'OneToNineInt',
min: 1,
max: 9,
});
new GraphQLObjectType({
name: 'Query',
fields: {
input: {
type: GraphQLInt,
args: {
number: {
type: argType,
},
},
resolve: (_, {number}) => {
// 'number' IS AN INT BETWEEN 1 to 9.
};
},
},
});
----
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace with type definition solution (server side)
mention: denial of service prevention

Comment on lines 479 to 485
==== Query cost points

The link:https://shopify.dev/docs/api/usage/limits#the-leaky-bucket-algorithm[leaky bucket algorithm].

==== Query cost analysis

link:https://github.com/pa-bru/graphql-cost-analysis[graphql-cost-analysis]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link to graphql armor

Comment on lines 490 to 496
To prevent the API from not responding or falling victim to denial of service attacks, it is feasible to make use of timeouts.
This way, subsequent queries will not be blocked by a long-running previous query.

There are many ways and places to use timeouts.
Here are a few examples.

// examples
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refer to transaction config in context

Comment on lines +10 to +12
. Set up a new AuraDB instance.
Refer to link:https://neo4j.com/docs/aura/getting-started/create-instance/[Creating a Neo4j Aura instance].
. Populate the instance with the Northwind data set.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure we want to make this a pre-requisite? This can also be done with an on-prem db

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's the same in graphql-modeling.adoc, following the "aura first" approach (making aura the default UX journey)


=== Authentication

The xref:security/authentication.adoc[`@authentication` directive] can be applied globally, only to certain fields or only to certain types, and only for certain operations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be applied globally but only to certain elements?

Is there a typo? I'm not sure I understand this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rephrased
it's either ... or ... or (added "either" and made it active voice)


The xref:security/authentication.adoc[`@authentication` directive] can be applied globally, only to certain fields or only to certain types, and only for certain operations.

Add admin authorization for operations on customers, orders, products, categories and suppliers:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use different directives to differentiate between authentication (we can identify who you are) and authorization (you have the correct rights to access the data)

While this particular example is a bit on the edge, I would avoid using the word "authorization" when trying to add examples of authentication to avoid confusion

In this case, we are validating your tokens are valid, including the role

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rephrased a bit

* *Reference*
* xref:security/index.adoc[]
** xref:security/securing-a-graphql-api.adoc[]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is reference the right place for this? this feels more like a tutorial

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right
security is in reference, but we have this nearly empty how-to section (we're going to tackle that next)
let's put it there for now 👍

----
type Customer
@node
@authentication( <1>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These points in the code are referenced with numbers, but I'm not sure what the reference to these are. Is this just to mark the code changes form the previous version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think i was going to do something with them, but then did not.
removed :)

Comment on lines 141 to 143
For instance, if the server side is trying to parse the `roles` field that was introduced in xref:#_authentication[], then the JWT should contain that.
With `@jwtClaim`, you can specify a path to a customer ID in a nested location.
For example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwtClaim is explained, but the directive @jwt is not mentioned anywhere, maybe worth mentioning that this directive allows to define the types of the jwt data?

Comment on lines 328 to 331
While the xref:getting-started/graphql-aura.adoc[Getting started page for GraphQL and Aura Console] advocates to both **Enable introspection** as well as **Enable field suggestions**, this is not recommended when considering security.

Both potentially expose information that can be used to gain insight on specifics of your GraphQL schema and execute targeted malicious operations.
Be sure to deactivate both in a customer-facing real-life scenario.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this is definitely recommended in production systems. Introspection and field suggestions are not necessarily insecure, and some applications, such as public APIs may want these features, may be worth rewording this to make sure these are recommendations, but not critical steps?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rephrased a bit


You can prevent denial of service attacks based on queries such as this by paginating query results.

A server-side pagination solution based on type definitions could look like this:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm, it feels like this example is missing the @limit directive that enforces limit

Or this is covering a different point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where would you place it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, I'm not sure what this example is covering, but if it is indeed server-side enforced pagination (https://neo4j.com/docs/graphql/current/directives/custom-logic/#_limit)

I'd say that we can add a @limit to any of the nodes of the initial typeDefinitions?

You can set a timeout via the GraphQL Library driver, see xref:driver-configuration.adoc#_transaction_configuration_in_context[Transaction configuration in context].


== Further reading
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend reading the GraphQL security section: https://www.graphql.org/learn/security/

This covers up to date best practices for GraphQL in general

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants