neo4j / graphql

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
https://neo4j.com/docs/graphql-manual/current/
Apache License 2.0
504 stars 149 forks source link

Fail to parse @authorization rules in GraphQL Schema (Invalid argument: validate, error: String cannot represent a non string value) #5681

Open mzvdev opened 11 hours ago

mzvdev commented 11 hours ago

Describe the bug We found that when we delete the yarn lock file in our current project, we had an error parsing the GraphQL Schema. It fails to parse @authorization rules (error message: Invalid argument: validate, error: String cannot represent a non string value) By removing @authorization rules it worked. Then we tried to isolate the problem in a separate repo, we still had the same issue.

Details Run tests by executing following commands:

yarn install
./test.sh watch-test

Test should now fail with:

...snipped...
 FAIL  src/index.test.js [ src/index.test.js ]
[
  {
    stack: 'GraphQLError: Invalid argument: validate, error: String cannot represent a non string value.\n' +
      '    at createGraphQLError (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/custom-rules/utils/document-validation-error.ts:83:12)\n' +
      '    at mapCustomRuleError (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/utils/map-error.ts:61:34)\n' +
      '    at mapError (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/utils/map-error.ts:29:16)\n' +
      '    at SDLValidationContext._onError (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/validate-sdl.ts:34:37)\n' +
      '    at SDLValidationContext.reportError (/n4j-issue/node_modules/graphql/validation/ValidationContext.js:36:10)\n' +
      '    at Object.Directive (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/custom-rules/directive-argument-of-correct-type.ts:100:33)\n' +
      '    at Object.enter (/n4j-issue/node_modules/graphql/language/visitor.js:301:32)\n' +
      '    at visit (/n4j-issue/node_modules/graphql/language/visitor.js:197:21)\n' +
      '    at validateSDL (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/validate-sdl.ts:38:10)\n' +
      '    at validateUserDefinition (/n4j-issue/node_modules/@neo4j/graphql/src/schema/validation/schema-validation.ts:106:31)',
    message: 'Invalid argument: validate, error: String cannot represent a non string value.',
    name: 'GraphQLError',
    path: [
      'User',
      '@authorization',
      'validate',
      0,
      'where',
      'node',
      'userId'
    ],
    originalError: undefined,
    nodes: undefined,
    source: undefined,
    positions: undefined,
    locations: undefined,
    extensions: {},
    constructor: 'Function<GraphQLError>',
    toString: 'Function<toString>',
    toJSON: 'Function<toJSON>'
  },
  stacks: []
]
...snipped...

Now if you remove following @authorization in schema.graphql:

  @authorization(
    validate: [
      { where: { node: { userId: "$jwt.sub" } } }
      { where: { jwt: { roles_INCLUDES: "admin" } } }
    ]
  )

Tests will now pass...

To Reproduce Steps to reproduce the behavior:

  1. Clone that repo: https://github.com/mzvdev/n4j-issues
  2. Install Yarn and Node.js
  3. Execute: ./test.sh watch-test
  4. See error

Expected behavior No errors parsing the schema

Environment

neo4j-team-graphql commented 8 hours ago

We've been able to confirm this bug using the steps to reproduce that you provided - many thanks @mzvdev! :pray: We will now prioritise the bug and address it appropriately.

darrellwarde commented 7 hours ago

Hey @mzvdev, I've been investigating this one and generally looking into the issues with the graphql-tools packages.

The issue here is actually in your type definitions! In your JWT you have defined sub as an integer (https://github.com/mzvdev/n4j-issues/blob/main/src/schema.graphql#L4) but then compare to it as a string (https://github.com/mzvdev/n4j-issues/blob/main/src/schema.graphql#L9).

This is a bit of a shortcoming of the authorization features because the $ string interpolation only really works with string variables. However, I have added a test to #5458 which proves that this all works when this definition is changed to String with the updated versions of graphql-tools.

mzvdev commented 6 hours ago

@darrellwarde Oups, Sorry! Thank you for finding. Indeed a type mistake from our side in the repo. But in the main project we have still that error, but the code is a bit different: GraphQLError: String cannot represent value: { where: { node: [Object] } }

type JWT @jwt {
    roles: [String]
    id: String
    sub: String
}
@authorization(
        validate: [
            { where: { node: { admins: { authId: "$jwt.id" } } } }
            { where: { node: { ref: "$jwt.sub" } }, operations: [READ] }
            { where: { jwt: { roles_INCLUDES: "overlord" } } }
        ]
    ) 

Will try to reproduce it again in my isolated repo and share it with you.

mzvdev commented 4 hours ago

@darrellwarde Quick question: is it possible to somehow identify which line cause an error? I have added the debug option, but not very helpful, to identify which line cause the error.

I have this error, but I have 50 places where I use { where: { node: {...} }, tried to isolate one by one, but not able to find it. GraphQLError: String cannot represent value: { where: { node: [Object] } }