Conversation
|
This PR includes documentation updates New pages: |
keremgocen
left a comment
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
Was this also a placeholder XY? feels like the JSON example here could be more illustrative?
|
|
||
| [source, graphql, indent=0] | ||
| ---- | ||
| // example |
There was a problem hiding this comment.
missing example here I think?
| There are many ways and places to use timeouts. | ||
| Here are a few examples. | ||
|
|
||
| // examples |
|
|
||
| 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? |
There was a problem hiding this comment.
also here, do we want an actual example?
| ---- | ||
| import depthLimit from 'graphql-depth-limit' | ||
| import express from 'express' | ||
| import graphqlHTTP from 'express-graphql' |
There was a problem hiding this comment.
should we maybe use a more up to date example here? we could replace the deprecated express-graphql with graphql-http, apparently. (cc: @mjfwebb)
There was a problem hiding this comment.
We'll replace this example with an example using GraphQL Armor
Co-authored-by: kerem <kerem.gocen@neo4j.com>
| 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. | ||
|
|
||
| }; | ||
| }, | ||
| }, | ||
| }); | ||
| ---- |
There was a problem hiding this comment.
replace with type definition solution (server side)
mention: denial of service prevention
| ==== 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] |
There was a problem hiding this comment.
link to graphql armor
| 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 |
There was a problem hiding this comment.
refer to transaction config in context
| . 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. |
There was a problem hiding this comment.
Are we sure we want to make this a pre-requisite? This can also be done with an on-prem db
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
can be applied globally but only to certain elements?
Is there a typo? I'm not sure I understand this
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
rephrased a bit
modules/ROOT/content-nav.adoc
Outdated
|
|
||
| * *Reference* | ||
| * xref:security/index.adoc[] | ||
| ** xref:security/securing-a-graphql-api.adoc[] |
There was a problem hiding this comment.
Is reference the right place for this? this feels more like a tutorial
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
i think i was going to do something with them, but then did not.
removed :)
| 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: |
There was a problem hiding this comment.
@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?
| 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
mmm, it feels like this example is missing the @limit directive that enforces limit
Or this is covering a different point?
There was a problem hiding this comment.
where would you place it?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
added the @limit on the Order type definition
| 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 |
There was a problem hiding this comment.
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
this PR is kinda dependent on #274 now
would be good to publish them simultaneously
274 has two js examples missing