Любая идея о том, как обрабатывать аутентификацию graphql-redis-subscriptions при использовании вместе с apollo-server

Я использую 'graphql-redis-subscriptions' из https://github.com/davidyaha/graphql-redis-subscriptions. Приведено несколько примеров того, как настроить подписки, и они действительно работают, но проблема, с которой я сталкиваюсь, заключается в том, как я могу аутентифицировать и разрешить прослушивание подписки только зарегистрированному клиентскому пользователю. Я использую Apollo-server для обслуживания API-интерфейсов graphql следующим образом:

const server = new ApolloServer({
            schema,
            dataSources,
            context: async ({ req, connection }) => {
                if (connection) {
                    return {
                        ...connection.context
                    };
                }

                const token = req.headers[API_TOKEN];

                return {
                    premiumAuth: token
                };
            },
        });
        server.listen(5000);

person PainPoints    schedule 19.02.2020    source источник
comment
Конечная точка веб-сокета подписки работает волшебным образом с добавлением следующего, но я не понимаю, почему? if (connection) { return { ...connection.context }; }   -  person PainPoints    schedule 19.02.2020


Ответы (1)


Аутентифицировано в context опции apollo-server для аутентификации запроса протокола HTTP. Это означает, что он будет защищать /graphql конечную точку от доступа без аутентификации. Например.

  const contextFunction: ContextFunction<IContextFunctionParams, IConnectors<IMemoryDB>> = (
    context: IContextFunctionParams,
  ): Context<IAppContext> => {
    const { req, connection } = context;
    if (connection) {
      return connection.context;
    } else {
      const token: string = validateToken(req);
      const userConnector = new UserConnector<IMemoryDB>(memoryDB);
      let user: IUser | undefined;
      try {
        const userType: UserType = UserType[token];
        user = userConnector.findUserByUserType(userType);
      } catch (error) {
        throw error;
      }
      return {
        requestingUser: user,
        locationConnector: new LocationConnector<IMemoryDB>(memoryDB),
        userConnector,
        templateConnector: new TemplateConnector<IMemoryDB>(
          memoryDB,
          pubsub,
          // postgresPubSub,
        ),
      };
    }
  };

Для подключения по протоколу WebSocket, от которого зависит подписка на graphql. Вам необходимо пройти аутентификацию внутри метода subscriptions.onConnect, например.

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: contextFunction,
    introspection: true,
    subscriptions: {
      onConnect: (
        connectionParams: IWebSocketConnectionParams,
        webSocket: WebSocket,
        connectionContext: ConnectionContext,
      ) => {
        console.log('websocket connect');
        console.log('connectionParams: ', connectionParams);
        if (connectionParams.token) {
          const token: string = validateToken(connectionParams.token);
          const userConnector = new UserConnector<IMemoryDB>(memoryDB);
          let user: IUser | undefined;
          try {
            const userType: UserType = UserType[token];
            user = userConnector.findUserByUserType(userType);
          } catch (error) {
            throw error;
          }

          const context: ISubscriptionContext = {
            // pubsub: postgresPubSub,
            pubsub,
            subscribeUser: user,
            userConnector,
            locationConnector: new LocationConnector<IMemoryDB>(memoryDB),
          };

          return context;
        }

        throw new Error('Missing auth token!');
      },
      onDisconnect: (webSocket: WebSocket, connectionContext: ConnectionContext) => {
        console.log('websocket disconnect');
      },
    },
  });

исходный код: https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/subscriptions

person slideshowp2    schedule 24.02.2020