graphql-auth-directives icon indicating copy to clipboard operation
graphql-auth-directives copied to clipboard

`next is not a function` when @isAuthenticated is used on GraphQL type or field

Open igokul1973 opened this issue 4 years ago • 2 comments

Hello!

Given I followed all the documentation regarding authentication on your site and added all the prerequisites for using the isAuthenticated directive, when an authenticated request (it happens ONLY when having access token in headers) involving a type or field annotated with @isAuthenticated is made, the following error comes back.

image

Here is the annotation: image

In order to fix it, I added the check for the next() existence in the src/index.js isAuthenticatedDirective class of your library (closer to the end of it):

export class IsAuthenticatedDirective extends SchemaDirectiveVisitor {
    static getDirectiveDeclaration(directiveName, schema) {
        return new GraphQLDirective({
            name: "isAuthenticated",
            locations: [DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT]
        });
    }

    visitObject(obj) {
        const fields = obj.getFields();

        Object.keys(fields).forEach(fieldName => {
            const field = fields[fieldName];
            const next = field.resolve;

            field.resolve = function (result, args, context, info) {
                verifyAndDecodeToken({context}); // will throw error if not valid signed jwt
                if (next) {
                    return next(result, args, context, info);
                }
                return result[field.name];
            };
        });
    }
}

Please fix it in the next possible release.

FYI - using the latest version of your library in the scope of neo4j-graphql-js as of today: image

igokul1973 avatar Sep 24 '19 14:09 igokul1973

Hi,

I was getting the same error but using the @hasRole directive.

I could see that the field.resolve returned undefined when the directive was applied.

Thanks @igokul1973 for share your solution to this issue.

In my case I added the if in two differents parts of the index.js


    key: "visitFieldDefinition",
.
.
.

        var roles = process.env.AUTH_DIRECTIVES_ROLE_KEY ? decoded[process.env.AUTH_DIRECTIVES_ROLE_KEY] || [] : decoded["Roles"] || decoded["roles"] || decoded["Role"] || decoded["role"] || [];

        if (expectedRoles.some(function (role) {
          return roles.indexOf(role) !== -1;
        })) {
          if (next) {
            return next(result, args, _objectSpread({}, context, {
              user: decoded
            }), info);
          }
          return result[field.name];
        }

and here

    key: "visitObject",
.
.
.
        if (expectedRoles.some(function (role) {
          return roles.indexOf(role) !== -1;
        })) {
          if (next) {
            return next(result, args, _objectSpread({}, context, {
              user: decoded
            }), info);
          }
          return result[field.name];
        }

version: "neo4j-driver": "^1.7.6", "neo4j-graphql-js": "^2.13.0", "graphql-auth-directives@^2.2.0"

rdimicheleb avatar Apr 08 '20 04:04 rdimicheleb

Please merge nino-vrijman's pull request to fix directives on fields.

ghost avatar Jun 16 '21 08:06 ghost