Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Express Middleware for Authentication/Authorization. #186

Closed
cellis opened this issue Oct 19, 2016 · 4 comments
Closed

How to use Express Middleware for Authentication/Authorization. #186

cellis opened this issue Oct 19, 2016 · 4 comments

Comments

@cellis
Copy link

cellis commented Oct 19, 2016

Hi, I'm wondering how to do authorization with Express Middleware. I know the docs suggest using the hooks provided, but I'm unsure how to proceed with e.g. a passport-js enabled api. How, for example, do I pass the req.user to the context, as suggested In this article. TLDR; i'm looking for how to do something like this:

app.post('/graphql', (req, res) => {
  graphql(schema, req.body, { user: req.user })
  .then((data) => {
    res.send(JSON.stringify(data));
  });
});

Because graffiti-express / graffiti-mongoose abstracts over the graphql library and provides itself as middleware, I'm not sure how to insert the req.user.

I've read the README, but understanding how the hooks work is also somewhat difficult to an uninitiated user. What are the meanings of singular, viewer, plural, and mutation and why do we need to provide each of them? How could I use the request argument in conjuction with passport.authenticate to authenticate the user?

Any help appreciated!

@cellis
Copy link
Author

cellis commented Oct 20, 2016

Upon closer inspection, i have figured this out. However the README should be updated as the request parameter is undefined, while the root parameter actually contains the request.

const schema = getSchema([User], { hooks: {
    singular: {
        pre: (next, root, args, request)=> {
            console.log(root.request.user);  // => { email: 'user@example.com' }
            console.log(request);            // => undefined
            next();
        },
        post: (next, value)=> {
            //...
            next();
        }
    }
}});

Perhaps the shifted signature of graphql@0.6.2 has something to do with it. Here's the signature at 0.6.2:

graphql(schema, requestString, rootValue, contextValue, variableValues, operationName) {

And here's what graffiti passes:

return graphql(schema, query, { request }, context, parsedVariables)...

at L41

@cellis cellis closed this as completed Nov 28, 2016
@katopz
Copy link

katopz commented Feb 12, 2017

@cellis for mutation is even more weird
doc

  mutation: {
    pre: (next, args, context) => next(),
    post: (next, value, args, context) => next()
  }

actually

  mutation: {
    pre: (next, args, context, what) => {
      console.log(what.rootValue.request.user);
      next();
    },
    post: (next, value, args, context) => {
      next();
    }
  }

And context is empty {}

@tothandras
Copy link
Contributor

Thanks for finding this! PR's are welcomed if you have time to fix it @cellis, @katopz!

@katopz
Copy link

katopz commented Feb 12, 2017

@tothandras I'm not sure PR for read me is enough, something really wrong there
Here's workaround for me atm

const hooks = {
  viewer: {
    pre: (next, args, foo, context, options) => {
      console.log(options.rootValue.request.user);
      next()
    },
    post: (next, value) => {
      next()
    }
  },
  singular: {
    pre: (next, root, args, request, options) => {
      console.log(options.rootValue.request.user);
      next();
    },
    post: (next, value, args, context) => {
      next();
    }
  },
  plural: {
    pre: (next, root, args, request, options) => {
      console.log(options.rootValue.request.user);
      next();
    },
    post: (next, value, args, context) => {
      next();
    }
  },
  mutation: {
    pre: (next, args, context, options) => {
      console.log(options.rootValue.request.user);
      next();
    },
    post: (next, value, args, context) => {
      next();
    }
  }
}

module.exports = hooks

Somehow nested viewer change an order of arguments, and here's a problem

  plural: {
    pre: (next, root, args, request, options) => {

      // Normal plural query will return `root.request.user` properly
      // But mutation with viewer plural will return `{_type: "Viewer", id: "viewer"}` 
      // and `root.request` will be `undefined`
      console.log(root.request.user);

      // Working both query, mutation
      console.log(options.rootValue.request.user);

      next();
    }

Took me a day to figure this out 🤕

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants