Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
148 views
in Technique[技术] by (71.8m points)

javascript - Fetching token from extension storage in React + Apollo GraphQL browser extension

I'm trying to create a browser extension using React and Apollo GraphQL. For background, I'm using the webextension-polyfill which is why I refer to the browser namespace as opposed to chrome.

In my index.tsx file, I try to set up my Apollo Client as follows:

// ... more imports ...
import App from './App'

const link = HttpLink({
  uri: 'http://localhost:8000/graphql/',
});

const authLink = setContext((_, { headers }) => {

  window.postMessage({ type: "GET_TOKEN" }, "*");

  // I need to fetch `token` from the the result of the above postMessage
  
  return {
    headers: {
      ...headers,
      authorization: token ? `JWT ${token}` : "",
    }
  }
})

export const client = new ApolloClient({
  link: authLink.concat(link),
  cache: new InMemoryCache()
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ApolloProvider>,
  document.getElementById("root")
);

Normally in a regular web app you'd store your token in localStorage, and fetch it from there like so localStorage.getItem("token").

But since this is a browser extension, I can't use localStorage and fetch from it across all tabs. I have to use browser.storage.local.

I can successfully save to the extension's browser.storage.local after the user signs in, so you can assume the token is available and can be fetched.

Since you cannot interact with browser.storage.local outside of the context of the extension, I have to send a message to my content.js script to tell it to fetch it from storage.

This is why I have window.postMessage({ type: "GET_TOKEN" }, "*"); above.

Then in my content.js file, I listen for the message, and send another message with the result:

window.addEventListener("message", function (event) {
   ...
   onDidReceiveMessage(event);
})

async function onDidReceiveMessage(event) {
   if (event.data.type && (event.data.type === "GET_TOKEN")) {
     const payload = JSON.parse(JSON.stringify({ type: "TOKEN_RESULT", token: await browser.storage.local.get("token") }));
     window.postMessage(payload, "*");
   }
}

My problem is now listening for this event and using it in the index.tsx file during my setup of Apollo Client.

In the index.tsx file, I've tried something along the lines of:

const authLink = setContext((_, { headers }) => {

  window.postMessage({ type: "GET_TOKEN" }, "*");

  window.addEventListener("message", function (event) {
    if (event.data.type && (event.data.type === "TOKEN_RESULT")) {
      token = event.data.token.token
    }
  });

  // the value of `event.data.token.token` in the listener is correct and successfully fetched
  // but can only really be used in the listener, I need it available to be used below
  // as part of this outer `setContext` for Apollo
  
  return {
    headers: {
      ...headers,
      authorization: token ? `JWT ${token}` : "",
    }
  }
})

How do I fetch the token out of storage in the context of a browser extension, if I need to use it in a setup up file like the one used to setup Apollo Client?

Any help or alternative approaches would be appreciated.

question from:https://stackoverflow.com/questions/65877921/fetching-token-from-extension-storage-in-react-apollo-graphql-browser-extensio

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...