Skip to content
This repository was archived by the owner on May 26, 2022. It is now read-only.
This repository was archived by the owner on May 26, 2022. It is now read-only.

Req Access Pattern Overrides ApolloServer's Context Config #4

Description

@Phylodome

Cross-post and extension of this issue, as it may be more readily addressed here.

At present, graphql-auth-directives usage effectively co-opts the entire context object via returning only one sub-field of the context object it processes:

const server = new ApolloServer({
  schema,
  context: ({ req }) => { /* Here we pluck the variable `req` from context, via a destructured fn param */
    return req; /* Here we substitute req for the entire context object from which it came */
  }
});

If we inspect graphql-auth-directives' verifyAndDecodeToken function, we find that it takes for granted that the context object is the req object, which would not be the case if one were to configure the context object with both driver and req, as is necessary when instantiating ApolloServer.

Presently, if one instantiates ApolloServer like so:

const driver = neo4j.driver(
  "bolt://localhost:7687",
  neo4j.auth.basic("neo4j", "letmein")
);
const server = new ApolloServer({
  schema,
  context: ({ req }) => {
    return {req, driver};
  }
});

Then the logic within graphql-auth-directives will no longer find the auth header:

var verifyAndDecodeToken = function verifyAndDecodeToken(_ref) {
  var context = _ref.context; /* <-- Note: I *will not* find the headers on "_ref.context.req" */
  if (
    !context ||
    !context.headers ||
    (!context.headers.authorization && !context.headers.Authorization)
  ) {
    throw new _errors.AuthorizationError({
      message: "No authorization token."
    });
  }

Perhaps something like (in ES6, rather than the transpiled output above):

const verifyAndDecodeToken = function verifyAndDecodeToken({context}) {
  const req = context instanceof http.IncomingMessage ? context : (context.req || context.request);
...

Which would maintain backwards compatibility while allowing for context objects that possess req as a property.

That said, this still has a bit of a code smell, as in the present code what's being called context isn't necessarily the context object in question: it's either the context or a req of type http.IncomingMessage.

Whereas the above suggestion should fix the issue in a backwards-compatible manner, it also unfortunately turns the local context variable into a polymorphic type whose name doesn't closely match its underlying reality (e.g. it's really contextOrReq).

Ideally the API for verifyAndDecodeToken would take the full context as its only argument, then look for a http.IncomingMessage at either of context.req or context.request, afterwards using the proper req semantics in reference to the object in question (req.headers, etc...). In this way the API of this library would make as few assumptions as possible concerning the structure of the context object passed to the ApolloServer constructor, and minimize semantic confusion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions