Apollo Websocket - Unable to initiate with new connection with latest JWT token

Viewed 72

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

0 Answers
Related