I'm having trouble identifying users who have connected with web sockets. Here is how you can reproduce this issue:
1) Create a new client and configure a WebSocketLink
with connectionParams
.
const wsLink = new WebSocketLink({
uri: `ws://localhost:3333`,
options: {
connectionParams: {
lazy: true,
authToken: localStorage.getItem('token')
}
}
});
At this point the user has not logged in, there is no token. The websocket also has not yet connected, because lazy
is set to true. It doesn't connect until until the first subscription has been sent, after the user has logged in.
When the user does log in, and the connection has been made, the authToken
is null because this value was set when the client was configured, not after the user has logged in.
subscriptionServer.onConnect = params => {
console.log('connected: ', params.authToken) // null
}
Queries and Mutations are authorized by concatenating links:
const httpLink = new HttpLink({ uri: GRAPHQL_ENDPOINT })
const authLink = new ApolloLink((operation, forward) => {
const token = localStorage.getItem('token')
if (token) {
operation.setContext({
headers: {
authorization: `bearer ${token}`
}
})
}
return forward(operation)
})
const httpAuthLink = authLink.concat(httpLink)
I can identify users this way because the token
is added to the authorization
header when the request has been sent after the user has logged in. The problem with the WebSocketLink
connection params is that it reads the token when the client is being configured before the user has logged in.
I've been able to find a temporary solution. After the user is identified and their token is saved to the browser, I refresh the page: window.location = '/'
. If feels so dirty though.
Any thoughts on adding onConnecting
and onDisconnect
methods to the constructor options
of the WebSocketLink
? This approach will prevent any need to refresh the page.
const wsLink = new WebSocketLink({
uri: `ws://localhost:3333`,
options: {
onConnecting: () => {
// Invoked just before the Socket initially connects
// returns additional connection params
return {
authToken: localStorage.getItem('token')
}
},
onDisconnect: () => {
// Invoked when the socket is disconnected
}
}
});
dont do that, try this:
connectionParams: () => ({
lazy: true,
authToken: localStorage.getItem('token')
})
Thank you @gpbaculio
Most helpful comment
dont do that, try this: