node.jsexpressgraphqljwtmiddleware

Cannot read properties of undefined (reading 'isAuth') in React and GraphQL application


I'm encountering an error when trying to create a post in my React application using a GraphQL mutation. The error message is:

{
  "errors": [
    {
      "message": "Cannot read properties of undefined (reading 'isAuth')",
      "status": 500
    }
  ],
  "data": {
    "createPost": null
  }
}

This suggests that the req.isAuth property is undefined when the mutation reaches my backend resolver. However, I'm sending the token in the Authorization header of my GraphQL request.

Here is how I am resolving createPost function

const createPost = async ({ postInput }, req) => {
  console.log(req);
  if (!req.isAuth) {
    const error = new Error("Not Authenticated");
    error.code = 401;
    throw error;
  }
  const errors = [];
  if (
    validator.isEmpty(postInput.title) ||
    !validator.isLength(postInput.title, { min: 5 })
  ) {
    errors.push("Title is invalid");
  }
  if (
    validator.isEmpty(postInput.content) ||
    !validator.isLength(postInput.content, { min: 5 })
  ) {
    errors.push("Content is invalid");
  }
  if (errors.length > 0) {
    const error = new Error("Invalid Input");
    error.data = errors;
    error.code = 422;
    throw error;
  }
  const user = await User.findById(req.userId);
  if (!user) {
    const error = new Error("Invalid User");
    error.code = 401;
    throw error;
  }
  const post = new Post({
    title: postInput.title,
    content: postInput.content,
    imageUrl: postInput.imageUrl,
    creator: user,
  });
  const createdPost = await post.save();
  user.posts.push(createdPost);
  console.log('Done Succesfully');
  return {
    ...createdPost._doc,
    _id: createdPost._id.toString(),
    createsAt: createdPost.createdAt.toISOString(),
    updatedAt: createdPost.updatedAt.toISOString(),
  };
};

This is my custom middleware which is used before

 app.use('/graphql',createHandler({
    schema: graphqlSchema,
    rootValue: graphqlResolver})
)
app.use((req, res, next) => {
  console.log("Auth middleware executed");
  const authHeader = req.get("Authorization");
  if (!authHeader) {
    req.isAuth = false;
    return next();
  }
  console.log(authHeader);
  const token = authHeader.split(" ")[1];
  let decodedToken;
  try {
    decodedToken = jwt.verify(token, SECRET_KEY);
  } catch (error) {
    req.isAuth = false;
    return next();
  }
  if (!decodedToken) {
    req.isAuth = false;
    return next();
  }
  req.userId = decodedToken.userId;
  req.isAuth = true;
  next();
});

Here's what I've tried:

React application for frontend. Express server with graphql-http and graphQL package for backend. JWT authentication with a secret key.

This is not a professional project I am learning this online and this code is just not working for me please help.


Solution

  • You're using an incorrect function signature for your mutation:

    const createPost = async ({ postInput }, req) => {
    

    Should be:

    const createPost = async (_, { postInput }, {req}) => {
    

    The first parameter is the parent (which should be undefined for a mutation), the second is the mutation variables, and the 3rd is the context of which req is a key.