I have a vue application that connects to a graphQL server using vue apollo. The vue-apollo.js code is as follows
const httpEndpoint = process.env.XXX;
const wsEndpoint = process.env.XXX;
let baseLink = new ApolloLink((operation, forward) => {
let isTokenExpired = isJwtExpired(token)
console.log('isExpired is:',isTokenExpired) ;
if (isTokenExpired) {
Auth.currentSession().then((data) => {
token = data.idToken.jwtToken
localStorage.setItem('JoT', JSON.stringify(token));
const headerData = token? {authorization: `Bearer ${token}`,}: {};
operation.setContext({headers: headerData})
return forward(operation)
})
} else {
token = JSON.parse(token);
const headerData = token? {authorization: `Bearer ${token}`,}: {};
operation.setContext({headers: headerData})
return forward(operation)
}
})
let observerLink = new ApolloLink((operation, forward) => {
return forward(operation)
})
const baseAndObserverLink = baseLink.concat(observerLink)
const errorLink = onError(error => {
console.log(JSON.stringify(error))
if (error.graphQLErrors) {
console.log("GraphQL Error detected")
if (error.graphQLErrors.extensions && error.graphQLErrors.extensions.code && error.graphQLErrors.extensions.code === 'invalid-jwt') {
console.log("JWT EXPIRED")
}
} else if (error.networkError && error.networkError.extensions && error.networkError.extensions.code && error.networkError.extensions.code === 'start-failed') {
console.log("GraphQL Error detected type 2")
console.log("Unable to Connect")
}else if (error.networkError && error.networkError.extensions && error.networkError.extensions.code && error.networkError.extensions.code === 'validation-failed') {
console.log("GraphQL Error detected type 3")
console.log("Validation Error")
}
else {
console.log(JSON.stringify(error))
}
})
var wsLink = new WebSocketLink({
uri: wsEndpoint,
options: {
reconnect: true,
lazy: true,
timeout: 30000,
connectionParams: async () => {
const token = JSON.parse(localStorage.getItem('JWT'));
return {
headers: {
Authorization: token ? `Bearer ${token}` : "",
},
}
},
},
});
export var filesRoot =
process.env.VUE_APP_FILES_ROOT ||
httpEndpoint.substr(0, httpEndpoint.indexOf('/graphql'));
Vue.prototype.$filesRoot = filesRoot;
var httpLink = new HttpLink({
uri: httpEndpoint,
});
var splitLLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
);
export var defaultOptions = {
httpEndpoint,
wsEndpoint,
tokenName: 'JWT',
persisting: false,
websocketsOnly: true,
ssr: false,
link:baseAndObserverLink.concat(errorLink).concat(splitLLink),
};
export function createProvider(options = {}) {
const { apolloClient, wsClient } = createApolloClient({
...defaultOptions,
...options,
});
apolloClient.wsClient = wsClient;
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
defaultOptions: {
$query: {
// fetchPolicy: 'cache-and-network',
},
},
async errorHandler(error) {
},
});
return apolloProvider;
}
This code when we first login works well. When I refetch a new token the query part gets updated with new context and everything works fine. However the websocket connection seems to keep using the old token to reinitialise connection. So far I couldn't find any suitable solution except for do a forced reload which reinitilises the entire app and wss conection can work as we have latest token being passed. Is there another way