apollographql / subscriptions-transport-ws

:arrows_clockwise: A WebSocket client + server for GraphQL subscriptions
https://www.npmjs.com/package/subscriptions-transport-ws
MIT License
1.52k stars 342 forks source link

The websocket upgrade request must include all http headers set on context #803

Closed Nohac closed 2 years ago

Nohac commented 4 years ago

When connecting to a ws endpoint, the upgrade request does not include the headers I set on the context, this is the code I'm using:

const authLink = setContext(async (_, {headers}) => {
  const auth = await authState.header();
  return {
    headers: {
      ...headers,
      ...auth,
    },
  };
});

const httpLink = createHttpLink({
  uri: http_uri,
});

const wsLink = new WebSocketLink({
  uri: ws_uri,
  options: {
    reconnect: true,
    connectionParams: async () => {
      const auth = await authState.header();
      return {headers: auth};
    },
  },
});

const splitLink = split(
  ({query}) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === "OperationDefinition" &&
      definition.operation === "subscription"
    );
  },
  wsLink,
  httpLink,
);

I expect the headers from the auth link to be provided when performing the websocket upgrade, this is because the server is behind a reverse proxy that expects an authorization header with a jwt bearer token, if this token is not provided, the connection is not able to upgrade.

This is the error I'm getting when the proxy authentication is enabled:

2.40e02233.chunk.js:2 WebSocket connection to 'wss://<omitted>' failed: Error during WebSocket handshake: Unexpected response code: 302

It works for everything that respects the authLInk middleware (query, mutations etc.), and websockets work when the proxy authentication is disabled.

I really hope this is easy to fix, this is a pretty big deal-braker for me.

Nohac commented 4 years ago

The more I read about this issue, the more it seems like this scenario is impossible to solve when using websockets, because some genius decided that you can't set headers manually when using the javascript websocket api..

If anyone has any suggestions on how to solve this, please let me know, if not, this issue can just be closed.

Additional info: I'm running Hasura in App Service on azure with AD authentication enabled. Similar issue on stackoverflow: https://stackoverflow.com/questions/56837316/azure-app-service-with-websockets-and-ad-authentication

PeteMac88 commented 3 years ago

Hey any update here. We have the same Problem and we need a way to add the Authorization header to the subscription request. I am really stuck here because all alternatives are unsafe. Help would be appreciated!

rafalp commented 3 years ago

WebSocket API has no support for custom HTTP headers as it is now. This is not limitation of this library but rather how browsers are implementing the WebSocket standard.