最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to share local storage auth token from my site to my WebExtension? - Stack Overflow

programmeradmin2浏览0评论

I have a bookmarking firefox/chrome WebExtension (using the standard popup, content and background scripts). My api servers have a /login route that returns a JSON Web Token and the web app stores that in its local storage. I have full control over the extension, api, and web apps.

The barefoot way to do this is to have users log in through the popup and save the auth token in the background.js to the WebExtension's local storage. But I would really like to only ask the user to authenticate on my site and have that same auth apply to the extension as well.

Is there a way to share the auth token? I see Pocket and a lot of others doing this, but I'm not sure how.

I have a bookmarking firefox/chrome WebExtension (using the standard popup, content and background scripts). My api servers have a /login route that returns a JSON Web Token and the web app stores that in its local storage. I have full control over the extension, api, and web apps.

The barefoot way to do this is to have users log in through the popup and save the auth token in the background.js to the WebExtension's local storage. But I would really like to only ask the user to authenticate on my site and have that same auth apply to the extension as well.

Is there a way to share the auth token? I see Pocket and a lot of others doing this, but I'm not sure how.

Share Improve this question edited Jun 16, 2017 at 6:49 user asked Jun 15, 2017 at 5:31 useruser 3,4567 gold badges36 silver badges68 bronze badges 6
  • The easiest way would probably be to send the auth token as a cookie. – Forivin Commented Jun 15, 2017 at 8:13
  • 2 You can read the site's localStorage using a content script, then copy the token in your background page localStorage via messaging. – woxxom Commented Jun 16, 2017 at 6:49
  • @wOxxOm good approach, was unaware that the content script could access an external site's local storage. In fact, I thought local storage was more secure than that. That will entail opening a new tab with mysite. though, but this is a worthwhile tradeoff for my use case. This is related: stackoverflow./questions/3937000/…. – user Commented Jun 16, 2017 at 6:53
  • 1 You can open your site in an iframe inside your background or popup, but that requires tinkering with content security policy in manifest, you can find answers that show how to do it. – woxxom Commented Jun 16, 2017 at 7:22
  • Curious why is this not more mon of an issue. Seems like many developers expect the auth state of their website to be the same in the extension. – user Commented Jun 21, 2017 at 1:03
 |  Show 1 more ment

2 Answers 2

Reset to default 8 +50

You could store the token as a cookie. Cookies work like localStorage, but with the extra that the're also by default wrapped into every HTTP request to the server. And here es the trick. Chrome Extension can gain access to HTTP requests, with the use of webRequest API. Thus it can take a peek into the request headers and know your cookies. Having that web token as a cookie makes it available to the extension.

But still you need to wait for your website to be opened by the user, to have HTTP requests flowing and ready to be peeked at, right? Not really. You can make make an ajax request directly from the extension.

Here's to illustrate how the whole thing would work:

manifest:

"permissions": [
          "webRequest",
          "webRequestBlocking",
          "*://*.my_site./*"
        ]

Background page:

function callback (details) {
    //
    token = func_extract_token_from_headers(details.requestHeaders);

    chrome.webRequest.onBeforeSendHeaders.removeListener(callback); 

    return {cancel: false} //     set to true to prevent the request 
                           //   from reaching  the server
}
chrome.webRequest.onBeforeSendHeaders.addListener (callback,
        {urls: ["http://www.my_site./*", "https://www.my_site./*"]},
        ["blocking", "requestHeaders"]);


var xurl = "https://www.my_site./";
var xhr = new XMLHttpRequest();
xhr.open("GET", xurl, true);
xhr.send();

I should mention that there's a cleaner way to do it, but it currently does not work due to CSP--Content Secutiry Policiy. Opening the website in an iframe inside the background page, as mentioned by wOxxOm in ments, should work, with added CSP whitelisting of the website. This approach would also avoid prompting the user for credentials, and would be cleaner. Unfortunately it's not currently working

EDIT:

Sorry, I was wrong about my last claim: that iframes opening external pages are blocked in background pages. To display it in the background page(or popup for that matter), simply whitelist for CSP -- shown below.

Apart from the business of opening the page in an iframe, you need to municate with it. That should be done using the window.postMessage API

Here's to exemplify how it all should e together:

Manifest:

// Whitelist your website
    "content_security_policy": "script-src 'self' https://my_site./; object-src 'self'"
// Have the background declared as html
  "background": { "page": "background.html"}

Background:

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
{
  if(event.origin == "https://my_site."); //   you may want to check the 
                                             // origin to be your site 
  chrome.storage.storage.local.set({'auth_token': event.data});  // the token
}

iframe = document.createElement('iframe');
iframe.src = "https://my_site./";
// Have a div ready to place iframe in
document.getElementById('div').appendChild(iframe);

iframe.contentWindow.postMessage("give_token", "https://my_site.")

The web page:

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
{
  if(event.origin == "your_extension_id_aeiou12345");
     event.source.postMessage(''+localStorage.auth_token, event.origin);
}

EDIT:

Also, to have the website display in an iframe, make sure the X-frame-options response header is not set to a blocking value. You can either remove it, or set it to a non-blocking value, or white-list the url of the extension.

Since my requirements were as simple as "I need auth token T from website W", here's what I did:

First, store a cookie on the main website with the auth token, even if its already in local storage.

On popup script, before rendering, call

browser.cookie.get({name: 'https://website-W.', name: 'auth_token'})
.then(function(cookie) {
     console.log(cookie); // {..., value: "bearer-token-value" }
     var token = cookie.value;
     // send message to background script to store cookie globally
     // continue rendering successfully
})
.catch(function(error) {
    console.error(error);
    // handle not logged in
})
发布评论

评论列表(0)

  1. 暂无评论