Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a GraphQL query providing an auth token with Apollo Server?

Apollo Server Integration testing documentation shows how to test simple queries using createTestClient:

const { query } = createTestClient(server);
const res = await query({ query: GET_LAUNCH, variables: { id: 1 } });

In the attempt to test a query which requires an authorization token, I have tried passing the jwtToken as an extra field to the object passed to query like below:

const res = await query({ 
  query: MY_QUERY, 
  http: { headers: { authorization: `Bearer ${jwtToken}` } },
});

Unfortunately this doesn't work. When trying to run it I get the following response:

{
  "http": {
    "headers": {}
  },
  "errors": [{
    "message": "must authenticate",
    "locations": [{
      "line": 2,
      "column": 3
    }],
    "path": ["myQuery"],
    "extensions": {
      "code": "UNAUTHENTICATED"
    }
  }],
  "data": {
    "myQuery": null
  }
}

Any idea how to properly test queries which require an authorization token?

Using:

  "devDependencies": {
    "jest": "^23.6.0",
    "apollo-server-testing": "^2.4.8"
  }
like image 554
Marco Lackovic Avatar asked Feb 28 '19 14:02

Marco Lackovic


People also ask

How do you do authentication and authorization in GraphQL?

Your GraphQL API probably needs to control which users can see and interact with the various data it provides. Authentication is determining whether a given user is logged in, and subsequently determining which user someone is. Authorization is then determining what a given user has permission to do or see.

How do you pass auth tokens in GraphQL playground?

Solution. Before you can successfully call the TimeLine Service from the GraphQL playground you must acquire an authentication token and configure the GraphQL Playground "HTTP HEADERS" tab (bottom of the playground interface) to pass it as a header with your calls to the TimeLine Service.

How does GraphQL react to Apollo?

We create the httpLink that will connect our ApolloClient instance with the GraphQL API. The GraphQL server will be running on http://localhost:4000 . We instantiate ApolloClient by passing in the httpLink and a new instance of an InMemoryCache . Finally, we render the root component of our React app.


1 Answers

You can create a new server instance with a separate context for your tests. Something like this (may not be 100% correct syntactically, but you'll get the idea):

// Create a test user, no need to mess with JWT here, just create a plain object
// that resembles a user in your system.
const testUser = {
  id: 'testId',
  email: '[email protected]',
};

// Use this for both test servers and real servers
export function getContext(models, viewer) {
  return {
    ...models,
    viewer,
  };
}

// Create test server
const testServer = new ApolloServer({
  typeDefs,
  resolvers,
  context: getContext({}, testUser),
});

const { query } = createTestClient(testServer);

// The actual server (you know better how this looks on your end, but just for
// the concept)
const realServer = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req, res }) => {
    const user = decodeUser(req.headers.authorization);

    return getContext({}, user);
  },
});
like image 125
Mikael Lirbank Avatar answered Sep 23 '22 12:09

Mikael Lirbank