I am working on a GraphQL server built using Express and attempting to support Relay.
For a regular GraphQL query, I can handle authorization in the resolve function. E.g.:
var queryType = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
foo: {
type: new GraphQLList(bar),
description: 'I should have access to some but not all instances of bar',
resolve: (root, args, request) => getBarsIHaveAccessTo(request.user)
}
})
});
To support Relay refetching on the back-end, Facebook's Relay tutorial instructs us to have GraphQL objects implement a nodeInterface for mapping global ids to objects and objects to GraphQL types. The nodeInterface is defined by the nodeDefinitions function from graphql-relay.
const {nodeInterface, nodeField} = nodeDefinitions(
(globalId) => {
const {type, id} = fromGlobalId(globalId);
if (type === 'bar') {
// since I don't have access to the request object here, I can't pass the user to getBar, so getBar can't perform authorization
return getBar(id);
} else {
return null;
}
},
(obj) => {
// return the object type
}
);
The refetching function that gets passed to nodeDefinitions doesn't get passed the request object, only the global id. How can I get access to the user during refetching so I can authorize those requests?
As a sanity check, I tried querying for nodes that the authenticated user doesn't otherwise have access to (and shouldn't) through the node interface, and got the requested data back:
{node(id:"id_of_something_unauthorized"){
... on bar {
field_this_user_shouldnt_see
}
}}
=>
{
"data": {
"node": {
"field_this_user_shouldnt_see": "a secret"
}
}
}