apollo-client: It is not possible to pass Authorization header to WebSocket
Intended outcome:
Since Apollo Client 2 it is not possible to pass custom HTTP Header to WebSocket connection. In Apollo Client 1 it was possible by Middleware
, but since version 2 it is not. I tried with additional link concat
, or by applying Middleware
to subscriptionClient
.
Sample with authorized link:
const httpLink = createHttpLink({ uri: `https://ws.server.local/graphql` });
const wsLink = new WebSocketLink({
uri: `wss://ws.server.local/graphql`,
options: {
reconnect: true,
},
});
const middlewareLink = new ApolloLink((operation, forward) => {
operation.setContext({
headers: {
authorization: getBearerToken() || null,
},
});
return forward(operation);
});
const authorizedLink = middlewareLink.concat(wsLink);
const link = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
authorizedLink,
httpLink,
);
const client = new ApolloClient({
link: link,
...
});
Sample with subscriptionClient Middleware
const httpLink = createHttpLink({ uri: `https://ws.server.local/graphql` });
const wsLink = new WebSocketLink({
uri: `wss://ws.server.local/graphql`,
options: {
reconnect: true,
},
});
const subscriptionMiddleware = {
applyMiddleware(options, next) {
console.log(options);
options.setContext({
headers: {
authorization: getBearerToken() || null,
},
});
next();
},
};
wsLink.subscriptionClient.use([subscriptionMiddleware]);
const link = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const client = new ApolloClient({
link: link,
...
});
Versions
System:
OS: macOS High Sierra 10.13.6
Binaries:
Node: 9.5.0 - /usr/local/bin/node
npm: 5.6.0 - /usr/local/bin/npm
Browsers:
Chrome: 69.0.3497.100
Firefox: 60.0.2
Safari: 12.0
npmPackages:
apollo-boost: ^0.1.3 => 0.1.15
apollo-client: ^2.4.2 => 2.4.2
apollo-link-ws: ^1.0.9 => 1.0.9
react-apollo: ^2.0.4 => 2.1.11
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 11
- Comments: 17
Struggled with adding async function for connection params, was getting
start received before the connection is initialised
error. Fixed it by addinglazy: true
to connection options:Just in case someone having the same issue.
@dreamer01 If i understand currently your question is like mine. If so then on WebSocketLink you can only pass tokens on connect. if your token expires and you get a new one, you need to reconnect with the new tokens. here is an example. And if that wasn’t your question, then maybe it will help someone else… 😃
@michal-hudy Does this not work for you?
@pyankoff I’m using Hasura as well. how did you handle token change (refresh after expiration) with WebSocketLink?
The code example by @pyankoff did not work for me.
Instead, I had to supply the auth token in
connectionParams.authorization
rather thanconnectionParams.headers.Authorization
:Finally an actual code example for how to refresh tokens with websocket properly! Pasting it here just because the past 2 examples I’ve been linked 404’d.
It took literally forever to find your comment with this example.
Hey, @pyankoff can you please share how you were able to re-authenticate the user once the token has expired. I am able to get new
accessToken
usingrefreshToken
but I am failing to pass the new accessToken to client. I have read through few examples and all direct towards usingoperation.setContext
, which I was unable to implement while usingWebSocketLink
.Thanks.
It won’t work as WebSocket API in browsers doesn’t support setting custom headers, apart from the value of
Sec-Websocket-Protocol
header. https://stackoverflow.com/questions/4361173/http-headers-in-websockets-client-api/41521871If I recall, yes -
// @ts-ignore
that thing and it will work I believe@georgyfarniev I think it depends on your server side implementation. I was using Hasura and didn’t have to handle it.