0

I'm using Apollo Federation, and I'd like to implement some custom auth behavior in the gateway, such as directly make a call to an implementing service from the gateway to get user data that I can then add as a header to be forwarded to the implementing services for the request. Is doing something like this possible? Is such a pattern common or not recommend?

David Brown
  • 133
  • 1
  • 10

1 Answers1

1

You can absolutely do this.

const gateway = new ApolloGateway({
  serviceList,
  buildService({ url, name }) {
    // Do something here to process stuff. If you're using RemoteGraphQLDataSource:
    return new RemoteGraphQLDataSource({
      url,
      name,
      willSendRequest({ request, context }): void {
        // This `context` is the object you're returning "down there"
        // Add content to your request
        if (context.viewer) {
          request.http.headers.set('something', 'data');
        }
      },
    });
  },
});

const server = new ApolloServer({
  gateway,
  // { req, res } is used for apollo-server (or apollo-server-express)
  // { event } is used for apollo-server-lambda
  context: async ({ req, res }) => {
    const authHeader = req.headers.Authorization', '');
    const accessToken = authHeader.replace(/Bearer /, '');
    const viewer = await someAsyncSomethingToGetTheUserData({ accessToken });

    // this is the `context` object you use "up there"
    return {
      viewer,
    };
  },
});

Some caveats:

  1. make sure if you're sending "trusted data" to your backing services that your backing services are not accessible by "regular clients". Otherwise, you would be trusting data that could be being sent by untrusted systems or people.
  2. Make sure you're not doing a lot of heavy lifting in this function, as you're doing it on every single request, whether your backing service needed it or not, and one of the values of GraphQL is you never do work that the client isn't specifically asking for.
Dan Crews
  • 3,067
  • 17
  • 20
  • So in the `// Do something here to process stuff` section, I could make a raw http request to one of the backing services to fetch data? – David Brown Jul 09 '20 at 20:04
  • No, @DavidBrown I would do that inside the `context` function where you create the `viewer` object. That is an `async` function. `buildService` is a synchronous function, which must return a GraphQLDataSource. – Dan Crews Jul 11 '20 at 17:40