Is it possible to apply graphql middleware when using managed federation

I have seen people apply graphql middleware (like graph-shield) to self-managed apollo federation servers like this:

const { schema: federatedSchema, executor } = await gateway.load();
  const schema = applyMiddleware(
    federatedSchema,
    shield(
      {
        Query: allow,
        Mutation: allow,
      },
      {
        debug: true,
      }
    )
  );
const server = new ApolloServer({
    schema,
    executor});

However, you can’t use this method when you are using a managed gateway without getting the “When a manual configuration is not provided, gateway requires an Apollo configuration” error.

We are using Apollo Studio and I’d like to keep the benefits of using managed federation, however, I need middleware.

1 Like

Sorry not an answer but I’m also interested in this, because if Apollo Federation is ever going to support GraphQL multipart requests then that will probably (if its anything like how its done in Apollo Server) be done via middleware.

1 Like

Not a satisfying solution but I managed to get graphql-shield working by hacking it in with Apollo Server plugins

This is my server code:

export const createServer = (serverConfig) => {
  return new ApolloServer({
    debug: process.env.NODE_ENV !== 'production',
    context: ({ req }: any): ServerContext => {
      const user = req?.user || {};

      return { user };
    },
    plugins: [
      {
        serverWillStart: async () => ({
          schemaDidLoadOrUpdate: ({ apiSchema }) => {
            shieldedSchema = applyMiddleware(apiSchema, permissions);
          },
        }),
        requestDidStart: async () => ({
          responseForOperation: async ({ document, context }) => {
            /**
             * This is jank to make graphql-shield work with a managed federated gateway.
             * Basically I execute the gql request against an empty schema that just has graphql-shield on it
             * If graphql-shield lets the request through it will return null (or an error if the field can't be null)
             * If I get a graphql-shield error, I return it (thus bypassing the actually remote execution)
             * Otherwise I return undefined so that it executes the actual gql request against the subgraph
             * **/
            const result = await execute({ schema: shieldedSchema, document, contextValue: context });
            const actualErrors = (result?.errors || []).filter(
              ({ message }) => !message.includes('Cannot return null for non-nullable field')
            );
            if (actualErrors.length === 0) {
              return undefined as any;
            }
            return result;
          },
        }),
      },
    ],
    formatError: (error: GraphQLError): GraphQLFormattedError => {
      if (error?.extensions?.errorType === 'PERMISSION_DENIED') {
        return new ForbiddenError('Access is denied.');
      }
      return error;
    },
    ...serverConfig,
  });
};