I was trying to add context information with headers (like in example https://www.apollographql.com/docs/react/recipes/authentication.html) but in my case I have WS link instead of HTTP.
const authLink = setContext((req, {headers}) => ({
headers: {
...headers,
authorization: '...'
}
}));
const client = new ApolloClient({
link: authLink.concat(wsLink),
cache: new InMemoryCache()
});
Context is not delivered to server, I checked it frames section in Network tab and in onOperation:
new SubscriptionServer({
execute,
subscribe,
schema,
onOperation: (message, params, webSocket) => {
console.log('onOperation', {message, params});
return params;
}
}, {
server: ws,
path: '/subscriptions',
});
Context is equal to {}.
Moreover, on client I get the following error when using WS:
bluebird.js:1546 Warning: a promise was created in a handler but was not returned from it, see http://goo.gl/rRqMUw
Everything works well with HTTP though.
I have traced the execution: WebSocketLink.request(operation) -> SubscriptionClient.request(operation), and the problem is that operation contain getContext getter:
{
extensions: {},
operationName: "Xxx"
query: {kind: "Document", definitions: Array(4), loc: {鈥}
variables: {},
getContext(),
setContext()
}
Which is never called in SubscriptionClient.
Any updates on this?
Any updates?
------------ EDIT:
For googlers, I ended up using the following:
const wsLink = new WebSocketLink({
uri: `ws://localhost:3004/graphql`,
options: {
reconnect: true,
connectionParams: () => ({
authorization: Cookie.get('token'),
}),
},
});
Works just like you were setting http headers on graphql playground:

could someone confirm that once the websocket channel has been opened (with Authorization header = token AAA), each subsequent request using the websocket link will always be identified as AAA token.
Or is there a way to send a different Authorization header on each request (other than re-opening another ws channel)?
I'd like to understand what's happening on a low level protocol for ws.
Thank you for you reply!
const wsClient = new SubscriptionClient(
graphqlEndpoint,
{
reconnect: true,
connectionParams: () => ({
headers: {
'Authorization': 'mytokenAAA',
},
}),
},
ws,
);
const link = new WebSocketLink(wsClient);
makePromise(execute(link, options)); // that's using token AAA
// how to make another query (execute) using token BBB without creating another link ?
Any update on dynamically pulling JWT tokens for wsLink? I'm getting all kinds of errors or non-response when I try and mirror setups for httpLink.
@hito you should be able to set using middleware of the SubscriptionClient. See my gist here: https://gist.github.com/cowlicks/71e766164647f224bf15f086ea34fa52
const subscriptionMiddleware = {
applyMiddleware: function(options, next) {
// Get the current context
const context = options.getContext();
// set it on the `options` which will be passed to the websocket with Apollo
// Server it becomes: `ApolloServer({contetx: ({payload}) => (returns options)
options.authorization = context.authorization;
next()
},
};
const server = new ApolloServer({
context: ({connection, payload, req}) => {
// whatever you return here can be accessed from the middleware of the SubscriptionMiddleware with
// applyMiddleware: (options, next) => options.getContext()
return {authorization: payload.authorization};
},
});
const link = new WebSocketLink({
uri: WS_URL,
webSocketImpl: WebSocket,
options: {
reconnect: true,
}
});
link.subscriptionClient.use([subscriptionMiddleware]);
Most helpful comment
Any updates?
------------ EDIT:
For googlers, I ended up using the following:
Works just like you were setting http headers on graphql playground: