Migrate localStorage data from HTTP to HTTPS - javascript

I've made a web app that stores persistent user data in localStorage. I've enabled HTTPS on my site, and I'd really like to flip the switch on HSTS. However, as far as I can tell, localStorage considers http://example.com and https://example.com to be different, so if existing users are redirected to the HTTPS version of my site, they can no longer access their data (though it still exists).
Long term, I want to build a new version of this app that offers more options for data storage. But in the short term, all I can think of is having a transition period where users at the http version are asked to migrate their data via some other (unknown) mechanism that both versions can access.
Is this a fair assessment of my options? Is there a way for https://example.com to access the localStorage of http://example.com? If not, is there anywhere I can put user data such that both versions can access it but other sites can't? Or should I ask them to download their data and re-upload it? That doesn't see ideal from a UX or (user) security standpoint.
Note that this web app doesn't interact with a server at all; everything happens with localStorage and the client.

Unfortunately there does not seem to be any way to directly retrieve localStorage contents for the less secure http copy of the site from the https site. reference
The workaround I have seen is to use an iframe loading a special page on the insecure site similar to this answer. The general theory is to have code in the iframe that sends messages using postMessage with localStorage data back to the secure page.
Unfortunately this approach does not allow you to disable http entirely, because otherwise your iframed http copy would not load.

Related

How to proxy all XMLHttpRequest in a web browser?

I'm using Google Firebase, and unfortunately, Google Firebase put some countries under sanctions which means they must use a proxy (or VPN) to access the website.
Is there any way I can set a proxy setting for each client request that they can freely access Firebase without a VPN?
I know there are options for Node.js, but I'm looking for a web browser solution. Firefox has this proxy settings, and Google Chrome also has some options for extension developers, but I need a solution that works just in a web page, and it means when a user comes to my website, he/she does not need to set a proxy to access Firebase.
Example: when a user comes to my website from (for example) Syria or Sudan, they don't need to set VPN for their browser, because I have done some proxy configuration in my website
Short answer: You can't do it website-only.
Longer answer / explanation:
I know there are options for Node.js,
Good... that could work. Deploy your own Node.js server on Heroku or the like, which proxies requests to Firebase.
but I'm looking for a web browser solution. Firefox has this proxy settings, and Google Chrome also has some options for extension developers, but
This could work too, but as I'm sure you've considered... that would rely on the end-users installing those extensions before attempting to visit your site.
I need a solution that works just in a web page,
Nope. Not possible. The Google servers will not respond to any request coming from a sanctioned country. If a request comes from a disallowed country, the Firebase servers won't respond with your website - instead they respond with a 403. Firebase won't send the website. Your website won't be sent to the client. It doesn't matter what your website contains, it will never be sent to those end users in the first place.
Even if you host the site elsewhere, and just use the Firebase database, it still won't work - for the same reasons. When the Firebase servers receive the request from a browser running in a sanctioned country, they respond with 403.
The question then becomes: How to make the request appear to come from outside the sanctioned country, from the website only?
You can't, not when you only control the website itself. That part of the request/response cycle is, for end-user protection purposes, handled by the browser. Browsers do not expose that functionality to webpages.
If you want to handle everything for your users, without them needing a VPN (desktop, or browser), your only choice will be to send the request to a different non-Google server (such as a Node.js server you host on Heroku or the like), which then makes the request to Firebase on their behalf, gets the response, and responds back to the client. That way, to the Firebase servers, it looks like the request is coming from X* location.
*X: Where ever the Heroku server is running.

Automatically login people on specific websites using Electron

I created a small application using Electron ( http://electron.atom.io ). I want to add a feature that automatically logs in people on specific websites, on any type of browser.
The way I though of this is if Electron automatically completes the username and password fields of the website OR it sends an ajax request using the website's window context ( inject himself somehow into the content ).
I know that is possible to achieve this if I create extensions for each browser but it will take too long.
Thank you
The problem you will face is all browsers are set to prevent what is known as cross-site scripting. Basically I can create a frame inside a page or within the same domain and manipulate the dom of this externally sourced frame but I can not do this with a source from another domain.
So scripting across to fill and submit the form won't work which leaves you to trying to send a HTTP GET or POST through AJAX. Which the problem we reach here is that the site you are logging into is likely to check the referring URL to ensure the referrer is from it's own domain. While technically jquery has a method of setting the referrer header, unfortunately the browser resets this header in any cross site transactions for security purposes.
So basically there is no way to accomplish this reliably from a browser side script as the browsers are very restrictive when it comes to security measures. You will be able to login via AJAX to any sites that don't check their referrer header, but other than that you would need an arrangement with the websites your logging into, or use a more unrestricted platform that will allow you to manipulate the DOM cross site or spoof the Referrer Headers.
I figured that I will use the following approach:
I've found where most browsers keep their cookies, so I will upload the cookies there. When the user accesses the browser, it will be automatically logged in.

Secure Browser Extension API requests

I can't believe that I'm asking this right now, but I have no idea how solve the following problem:
I have a web app that logs every visited page in a browser for better browser history search. The extension is a chrome extension that needs to make a POST request to my API. Obviously, I need to avoid CSRF issues, i.e. other sites using the user's session to post arbitrary data to his browser history. However, since the extension runs in a different origin as a content-script, I cannot retrieve CSRF tokens, hence I cannot make authenticated POST requests.
EDIT:
So I now know that I can use chrome.storage (and equivalents in other browsers) to store a token that only my content_script can read. However, I still haven't solved the issue of how getting that token into chrome.storage in the first place
I seem to miss something really obvious ...
I suspect a content script isn't necessary, and you should just be using the chrome.webNavigation API from your event page to get the user's browsing activity.
You'll still need the user to log into your service somewhere in the browser. If you take your service's origin as a host permission, your extension will be able to make XHRs as the user, which may be enough to solve your XSRF problem, at least as long as nobody else can intercept the user's login cookies.
FYI, I realized that chrome.storage provides a means to sync/pass confidential data like your token that is only accessible to your scripts.
Hence, the solution is to visit a webpage of yours, and have a content script extract the token and store it in chrome.storage.

Secure JavaScript Running on 3rd Party Sites

We have a "widget" that runs on 3rd party websites, that is, anyone who signs up with our service and embeds the JavaScript.
At the moment we use JSONP for all communication. We can securely sign people in and create accounts via the use of an iFrame and some magic with detecting load events on it. (Essentially, we wait until the iFrames source is pointing back to the clients domain before reading a success value out of the title of it).
Because we're running on JSONP, we can use the browsers HTTP cookies to detect if the user is logged in.
However, we're in the process of transitioning our system to run realtime and over web sockets. We will still have the same method for authentication but we won't necessarily be making other calls using JSONP. Instead those calls will occur over websockets (using the library Faye)
How can I secure this? The potential security holes is if someone copies the JavaScript off an existing site, alters it, then gets people to visit their site instead. I think this defeats my original idea of sending back a secure token on login as the malicious JavaScript would be able to read it then use it perform authenticated actions.
Am I better off keeping my secure actions running over regular JSONP and my updates over WebSockets?
Websocket connections receive cookies only during the opening handshake. The only site that can access your websocket connection is the one that opened it, so if you're opening your connection after authentication then I presume your security will be comparable to your current JSONP implementation.
That is not to say that your JSONP implementation is secure. I don't know that it isn't, but are you checking the referrers for your JSONP requests to ensure they're really coming from the same 3rd-party site that logged in? If not, you already have a security issue from other sites embedding your javascript.
In any case, the 3rd-party having an XSS vulnerability would also be a very big problem, but presumably you know that already.
Whether you are sent cookies during opening WebSocket handshake by browser (and if so, what cookies) is not specified by the WS spec. It's left up to browser vendors.
A WS connection can be opened to any site, not only the site originally serving the JS doing the connection. However, browsers MUST set the "Origin" HTTP header in the WS opening handshake to the one originally serving the JS. The server is then free to accept or deny the connection.
You could i.e. generate a random string in JS, store that client side, and let that plus the client IP take part in computing an auth token for WS ..

Are cookies the only native cross-subdomain storage?

Cookies are great because a value written in website.com can be used in www.website.com (www is considered a sudomain of no-www). The downside is all the cookie values are sent along with every HTTP request to the server. So I'm looking for a local storage mechanism available natively to Javascript that works cross-subdomain and isn't transmitted to the server. Does such a mechanism exist? LocalStorage doesn't work cross-subdomain and Flash Cookies wouldn't work on iPhone.
Perhaps just redirect website.com to www.website.com or vice versa?
This seems like it would be the simplest fix.
http://www.scriptalicious.com/blog/2009/04/redirecting-www-to-non-www-using-htaccess/
If your users have an actual account that they login to on your server, then you could store the info server-side and just include a little javascript in the each page that will need that data with the appropriate data. When you render the page server-side, you can define a user object in javascript with appropriate attributes set to the data values that can then be referenced client-side. That way, you only include the data that is needed in a given page, the same user data is available no matter what computer the user logs in from (no reliance on persistent cookies). If larger pieces of data are needed only occasionally and you don't want to include them in the page in case they are needed, then make those pieces of data queryable via ajax/json so they can be retrieved only when needed.
If you're still intent on only storing it locally, then cookies or HTML5 local storage are your only options and cookies will be your only cross browser option that covers all browsers in use. At the addition of implementation complexity, you could combine a number of the suggestions:
Always redirect to www.domain.com so all user activity is on the same domain.
Use HTML5 local storage when available (the redirect in step 1 prevents sub-domain lockout).
Fall back to cookie storage when HTML5 local storage is not available.
One could presumably write or find an abstraction for HTML5 local storage and cookies so 99% of your code could be independent of which storage mechanism was actually being used. It looks like there are some jQuery plugins that do exactly that.

Categories