Search code examples
javascriptgoogle-chrome-extensiongraphqlapollo

Why can I send GraphQL requests from the Chrome Apollo extension but I can't with my own extension?


I'm developing a chrome extension that sends existing GraphQL queries to a site.

Testing with the Apollo chrome extension, I managed to send my query correctly.

enter image description here

But when I do it via my script, I seem to get an authentication error: "User is not a workspace admin".

enter image description here

My query is called out of a chrome.scripting.executeScript and limited to:

const doSomething = async () => {
    
    const query = JSON.stringify({
        query: `MY QUERY`
    });
    const response = await fetch(TARGET_URL, {
        headers: { 'content-type': 'application/json' },
        method: 'POST',
        body: query,
    });

    const responseJson = await response.json();
    console.log(responseJson);
    return responseJson.data;
};

chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {

    chrome.scripting.executeScript({
        target: { tabId: tabs[0].id },
        func: doSomething
    }, (result) => {
        console.log(result[0].result);
    });
});

const responseJson = await response.json();
console.log(responseJson);

I think I'm missing an authentication step, but I don't understand why I have a difference between the Apollo extension and mine.

How does Apollo manage to execute its request? How can I update my script to achieve something similar?


Solution

  • As @phry mentioned, we send the request through your Apollo Client instance detected by the Chrome extension (whatever is set to window.__APOLLO_CLIENT__). This means that the request will go through your link chain as well, which may include some logic to attach authentication headers to the request.

    Looking at your code sample, I don't see any additional header information set in your fetch request, so that request is likely not authenticated the same way. If you want to check what your app's Apollo Client instance is sending, you can override the fetch function on HttpLink and log the request.

    createHttpLink({
      fetch: (uri, options) => {
        console.log(uri, options)
    
        return window.fetch(uri, options);
      }
    })
    
    // or if you use the constructor to create the link
    new HttpLink({
      fetch: (uri, options) => {
        console.log(uri, options)
    
        return window.fetch(uri, options);
      }
    })
    

    Just make sure the fetch function in your script includes any of the needed authentication headers that you see here. Hope this helps!