graphql
graphql copied to clipboard
Custom directives don't get access to auth context
Hello Neo4J Team!
Describe the bug
The new custom directives, wrap resolvers after neo4j/graphql
has already wrapped them with the auth wrapper.
That means custom directives don't get access to the auth context.
Not sure if it needs to be considered as a bug, but for me, it change the way I was working with this library.
Illustration:
[ custom resolver ] -> [ neo4j auth wrapper ] -> [ original resolver ]
To Reproduce
function creatorsOnlyDirective(directiveName: string): (schema: GraphQLSchema) => GraphQLSchema {
return (schema) =>
mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
const creatorsOnlyDirective = getDirective(schema, fieldConfig, directiveName)?.[0];
if (creatorsOnlyDirective) {
const { resolve = defaultFieldResolver } = fieldConfig;
return {
...fieldConfig,
resolver: async function (source, args, context, info) {
console.log(context.auth);
if (!context?.auth?.jwt?.roles?.includes?.("creator"))
throw new ForbiddenError("You are not a creator");
if (!context?.auth?.jwt?.roles?.includes?.("verified"))
throw new ForbiddenError("You account is not verified");
return resolve(source, args, context, info);
},
};
}
},
});
}
With this creatorsOnlyDirective
transformer - or any other - you will see that there is no auth context available.
Expected behavior
Illustration:
[ neo4j auth wrapper ] -> [ custom resolver ] -> [ original resolver ]
Maybe a transformers
field in the Neo4jGraphQLConstructor
to apply transformers before the auth wrapper.
const neoSchema: Neo4jGraphQLConstructor = {
resolvers,
typeDefs: [...directivesTypeDefs, typeDefs],
tramformers: [creatorsOnlyDirective],
plugins: {
auth: new Neo4jGraphQLAuthJWTPlugin({
secret: process.env.PWT_SECRET,
}),
},
driver,
};
System (please complete the following information):
- OS: linux (ubuntu)
- Version: @neo4j/graphql@^3.0.2
- Node.js version: v12.22.3
Many thanks for raising this bug report @mathix420. :bug: We will now attempt to reproduce the bug based on the steps you have provided.
Please ensure that you've provided the necessary information for a minimal reproduction, including but not limited to:
- Type definitions
- Resolvers
- Query and/or Mutation (or multiple) needed to reproduce
If you have a support agreement with Neo4j, please link this GitHub issue to a new or existing Zendesk ticket.
Thanks again! :pray:
Hey @mathix420, this is interesting, can you give some details about how and where you applying this custom directive?
I'm a bit confused by this issue, because the custom directive "extracts" the resolver out of the field, which should already have the populated because it was "reached" via either a Query or Mutation field which is wrapped here: https://github.com/neo4j/graphql/blob/dev/packages/graphql/src/classes/Neo4jGraphQL.ts#L153
So quite intrigued as to why the extracted resolver doesn't have this custom context.
Hello @darrellwarde,
If I'm not missleading, we should implement custom directives like this.
const neoGql = new Neo4jGraphQL({
resolvers,
typeDefs: [directiveTypeDef, typeDefs],
transformers: [transformer],
plugins: {
auth: new Neo4jGraphQLAuthJWTPlugin({
secret: process.env.PWT_SECRET,
}),
},
driver,
});
const schema = directiveTransformer(await neoGql.getSchema())
As you can see with this represntation, in the Custom directive wrapper
we can't have access to the auth context as the Auth wrapper
(which is responsible for injecting auth in the context) is still not executed.
As I understand this (https://github.com/neo4j/graphql/blob/dev/packages/graphql/src/classes/Neo4jGraphQL.ts#L153), it does not wrap the Query
field but all the resolvers of the fields inside Query
or Mutation
field.
Also I wanted to point out that it's been some months that I haven't worked with graphql, so I may be totally misleaded.. I hope it's not the case but at least you're aware of that.