I want to reduce load times on my websites by moving all cookies into local storage since they seem to have the same functionality. Are there any pros/cons (especially performance-wise) in using local storage to replace cookie functionality except for the obvious compatibility issues?
Cookies and local storage serve different purposes. Cookies are primarily for reading server-side, local storage can only be read by the client-side. So the question is, in your app, who needs this data — the client or the server?
If it's your client (your JavaScript), then by all means switch. You're wasting bandwidth by sending all the data in each HTTP header.
If it's your server, local storage isn't so useful because you'd have to forward the data along somehow (with Ajax or hidden form fields or something). This might be okay if the server only needs a small subset of the total data for each request.
You'll want to leave your session cookie as a cookie either way though.
As per the technical difference, and also my understanding:
Apart from being an old way of saving data, Cookies give you a limit of 4096 bytes (4095, actually) — it's per cookie. Local Storage is as big as 10MB per domain — this Stack Overflow question also mentions it.
localStorage is an implementation of the Storage Interface. It stores data with no expiration date, and gets cleared only through JavaScript, or clearing the Browser Cache / Locally Stored Data — unlike cookie expiry.
In the context of JWTs, Stormpath have written a fairly helpful article outlining possible ways to store them, and the (dis-)advantages pertaining to each method.
It also has a short overview of XSS and CSRF attacks, and how you can combat them.
I've attached some short snippets of the article below, in case their article is taken offline/their site goes down.
Local Storage
Problems:
Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS in a nutshell is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts alert('You are Hacked'); into a form to see if it is run by the browser and can be viewed by other users.
Prevention:
To prevent XSS, the common response is to escape and encode all untrusted data. But this is far from the full story. In 2015, modern web apps use JavaScript hosted on CDNs or outside infrastructure. Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.
What if only one of the scripts you use is compromised? Malicious
JavaScript can be embedded on the page, and Web Storage is
compromised. These types of XSS attacks can get everyone’s Web Storage
that visits your site, without their knowledge. This is probably why a
bunch of organizations advise not to store anything of value or trust
any information in web storage. This includes session identifiers and
tokens.
As a storage mechanism, Web Storage does not enforce any secure
standards during transfer. Whoever reads Web Storage and uses it must
do their due diligence to ensure they always send the JWT over HTTPS
and never HTTP.
Cookies
Problems:
Cookies, when used with the HttpOnly cookie flag, are not accessible through JavaScript, and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS. This is one of the main reasons that cookies have been leveraged in the past to store tokens or session data. Modern developers are hesitant to use cookies because they traditionally required state to be stored on the server, thus breaking RESTful best practices. Cookies as a storage mechanism do not require state to be stored on the server if you are storing a JWT in the cookie. This is because the JWT encapsulates everything the server needs to serve the request.
However, cookies are vulnerable to a different type of attack:
cross-site request forgery (CSRF). A CSRF attack is a type of attack
that occurs when a malicious web site, email, or blog causes a user’s
web browser to perform an unwanted action on a trusted site on which
the user is currently authenticated. This is an exploit of how the
browser handles cookies. A cookie can only be sent to the domains in
which it is allowed. By default, this is the domain that originally
set the cookie. The cookie will be sent for a request regardless of
whether you are on galaxies.com or hahagonnahackyou.com.
Prevention:
Modern browsers support the SameSite flag, in addition to HttpOnly and Secure. The purpose of this flag is to prevent the cookie from being transmitted in cross-site requests, preventing many kinds of CSRF attack.
For browsers that do not support SameSite, CSRF can be prevented by using synchronized token patterns. This
sounds complicated, but all modern web frameworks have support for
this.
For example, AngularJS has a solution to validate that the cookie is
accessible by only your domain. Straight from AngularJS docs:
When performing XHR requests, the $http service reads a token from a
cookie (by default, XSRF-TOKEN) and sets it as an HTTP header
(X-XSRF-TOKEN). Since only JavaScript that runs on your domain can
read the cookie, your server can be assured that the XHR came from
JavaScript running on your domain. You can make this CSRF protection
stateless by including a xsrfToken JWT claim:
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
Leveraging your web app framework’s CSRF protection makes cookies rock
solid for storing a JWT. CSRF can also be partially prevented by
checking the HTTP Referer and Origin header from your API. CSRF
attacks will have Referer and Origin headers that are unrelated to
your application.
The full article can be found here:
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
They also have a helpful article on how to best design and implement JWTs, with regards to the structure of the token itself:
https://stormpath.com/blog/jwt-the-right-way/
With localStorage, web applications can store data locally within the user's browser. Before HTML5, application data had to be stored in cookies, included in every server request. Large amounts of data can be stored locally, without affecting website performance. Although localStorage is more modern, there are some pros and cons to both techniques.
Cookies
Pros
Legacy support (it's been around forever)
Persistent data
Expiration dates
Cookies can be marked as HTTPOnly which might limit XSS atacks to user browser during his sesion (does not guarantee full immunity to XSS atacks).
Cons
Each domain stores all its cookies in a single string, which can make
parsing data difficult
Data is unencrypted, which becomes an issue because... ... though
small in size, cookies are sent with every HTTP request Limited size
(4KB)
Local storage
Pros
Support by most modern browsers
Persistent data that is stored directly in the browser
Same-origin rules apply to local storage data
Is not sent with every HTTP request
~5MB storage per domain (that's 5120KB)
Cons
Not supported by anything before: IE 8, Firefox 3.5, Safari 4, Chrome 4, Opera 10.5, iOS 2.0, Android 2.0
If the server needs stored client information you purposely have
to send it.
localStorage usage is almost identical with the session one. They have pretty much exact methods, so switching from session to localStorage is really child's play. However, if stored data is really crucial for your application, you will probably use cookies as a backup in case localStorage is not available. If you want to check browser support for localStorage, all you have to do is run this simple script:
/*
* function body that test if storage is available
* returns true if localStorage is available and false if it's not
*/
function lsTest(){
var test = 'test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
/*
* execute Test and run our custom script
*/
if(lsTest()) {
// window.sessionStorage.setItem(name, 1); // session and storage methods are very similar
window.localStorage.setItem(name, 1);
console.log('localStorage where used'); // log
} else {
document.cookie="name=1; expires=Mon, 28 Mar 2016 12:00:00 UTC";
console.log('Cookie where used'); // log
}
"localStorage values on Secure (SSL) pages are isolated"
as someone noticed keep in mind that localStorage will not be
available if you switch from 'http' to 'https' secured protocol, where
the cookie will still be accesible. This is kind of important to
be aware of if you work with secure protocols.
Cookies:
Introduced prior to HTML5.
Has expiration date.
Cleared by JS or by Clear Browsing Data of browser or after expiration date.
Will sent to the server per each request.
The capacity is 4KB.
Only strings are able to store in cookies.
There are two types of cookies: persistent and session.
Local Storage:
Introduced with HTML5.
Does not have expiration date.
Cleared by JS or by Clear Browsing Data of the browser.
You can select when the data must be sent to the server.
The capacity is 5MB.
Data is stored indefinitely, and must be a string.
Only have one type.
Key Differences:
Capacity:
Local Storage: 10MB
Cookies: 4kb
Browser Support:
Local Storage: HTML5
Cookies: HTML4, HTML5
Storage Location:
Local Storage: Browser Only
Cookies: Browser & Server
Send With Request:
Local Storage: Yes
Cookies: No
Accessed From:
Local Storage: Any Window
Cookies: Any Window.
Expiry Date:
Local Storage: Never Expire, until done by javascript.
Cookies: Yes, Have expiry date.
Note: Use that, what suits you.
It is also worth mentioning that localStorage cannot be used when users browse in "private" mode in some versions of mobile Safari.
Quoted from WayBack Archive of MDN topic on Window.localStorage back in 2018:
Note: Starting with iOS 5.1, Safari Mobile stores localStorage data in the cache folder, which is subject to occasional clean up, at the behest of the OS, typically if space is short. Safari Mobile's Private Browsing mode also prevents writing to localStorage entirely.
Cookie:
is accessible by JavaScript so Cookie's data can be stolen by XSS
attack(Cross Site Scripting attack) but setting HttpOnly flag
to Cookie prevents the access by JavaScript so Cookie's data is
protected from XSS attack.
is vulnerable to CSRF(Cross Site Request Forgery) but setting
SameSite flag with Lax to Cookie mitigates CSRF and setting SameSite flag with Strict to Cookie prevents
CSRF.
must have expiry date so when expiry date passes, Cookie is
deleted automatically so even if you forgot to delete Cookie,
Cookie is deleted automatically because of expiry date.
is about 4KB as a common size (depending on browsers).
Local Storage:
is accessible by JavaScript so Local Storage's data can be stolen by XSS
attack(Cross Site Scripting attack) then, as logn as I researched,
there are no easy preventions for Local Storage from XSS
attack.
is not vulnerable to CSRF(Cross Site Request Forgery).
doesn't have expiry date so if you forgot to delete Local Storage
data, Local Storage data can stay forever.
is about 5MB as a common size (depending on browsers).
I recommend using Cookie for sensitive data and Local Storage for non-sensitive data.
Well, local storage speed greatly depends on the browser the client is using, as well as the operating system. Chrome or Safari on a mac could be much faster than Firefox on a PC, especially with newer APIs. As always though, testing is your friend (I could not find any benchmarks).
I really don't see a huge difference in cookie vs local storage. Also, you should be more worried about compatibility issues: not all browsers have even begun to support the new HTML5 APIs, so cookies would be your best bet for speed and compatibility.
Local storage can store up to 5mb offline data, whereas session can also store up to 5 mb data. But cookies can store only 4kb data in text format.
LOCAl and Session storage data in JSON format, thus easy to parse. But cookies data is in string format.
I am new to angularjs. I want to pass localstorage variable from one angularjs project to another angularjs project. Both projects are on same server.
I am passing localstorage variable from http://site1.in/ as,
window.localStorage.setItem('is_provider', 1);
and I want to use this localstorage variable to http://site2.in/.
I don't know how to get this variable in site2.
Please help.
You can't, localStorage is per domain specific.
Local Storage Privacy
Website A and Website B would have their own local storage. Usually you would have to store certain information in a server database and sync it to the local storage.
I would use the local storage as a cache to get data once and update it at a certain interval depending on when I would want to invalidate the cache. For instance, you could sync with the server when the user A would log out and user B would want to login.
Have a look at the Privacy section in the HTML5 spec for Web Storage.
More information information and resources here: HTML5 Rocks.
Testing
I would suggest the use of a local server setup such as Linux/Mac/Windows, Apache, MySQL, PHP stack (LAMP/MAMP/WAMP) to test on localhost (127.0.0.1).
Most browsers will limit you to 5 MB per domain for every window and tab because of the HTML5 spec recommendation.
I haven't tried this, but you could perhaps have a look at changing the port number of the localhost in Apache's httpd.conf (to do so, find Listen and change the port associated to it) and see if this will do the trick. Basically, you run each test under a different port number to have the whole storage limit for each test.
An alternative would be to create a Chrome extension. You can read more information about this here:
Managing HTML5 Offline Storage
Manifest files
Maybe this link can help: http://www.nczonline.net/blog/2010/09/07/learning-from-xauth-cross-domain-localstorage/
And NO they cannot be without trickery
I found a way to pass data from one domain to another. You can use cross domain local storage to send data. I have used this and it's very simple. Refer to the site https://github.com/ofirdagan/cross-domain-local-storage
Currently we are using localStorage as persistent storage in our application. But we noticed that it is prone to data loss. Here is some links which supports this:
HTML5 Local Storage Not Persistent
localStorage data persistence
http://www.sencha.com/forum/showthread.php?132952-localstorage-doesn-t-save-all-data
So now I'm searching for a new solution. It will be good if this solution is supported by chrome/safari at iOS/Android. Could someone suggest something?
if its a website then, there is no means of persistent storage on browser. localstorage, database, cookies, everything is erased if user don't require them. So the only option would be to store the data on the server.
OR
if it is a mobile app (phonegap), then you can use SQL Lite.
I'm depending heavily on localStorage for a plugin I'm writing. All the user settings are stored in it. Some settings require the user the write regex'es and they would be sad if their regex rules are gone at some point.
So now I am wondering just how persistent the localStorage is.
From the specs:
User agents should expire data from the local storage areas only for security reasons or when requested to do so by the user.
The above looks like it works just like cookies on the clientside. I.e. when the user clears all browser data (history, cookies, cache etc) the localStorage will also be truncated. Is this assumption correct?
Mozilla implements it like cookies:
DOM Storage can be cleared via "Tools -> Clear Recent History -> Cookies" when Time range is "Everything" (via nsICookieManager::removeAll)
https://developer.mozilla.org/en/DOM/Storage
In DOM Storage it is not possible to specify an expiration period for any of your data. All expiration rules are left up to the user. In the case of Mozilla, most of those rules are inherited from the Cookie-related expiration rules. Because of this you can probably expect most of your DOM Storage data to last at least for a meaningful amount of time.
http://ejohn.org/blog/dom-storage/
Chrome implements it like cache:
LocalStorage is Not Secure Storage
HTML5 local storage saves data unencrypted in string form in the regular browser cache.
Persistence
On disk until deleted by user (delete cache) or by the app
https://developers.google.com/web-toolkit/doc/latest/DevGuideHtml5Storage
As for a "replacement for the Cookie", not entirely
Cookies and local storage really serve difference purposes. Cookies are primarily for reading server-side, LocalStorage can only be read client-side. So the question is, in your app, who needs this data — the client or the server?
Basically, you should not heavily depend on Local Storage.
Local Storage, along with Session Storage, aims to be a replacement of the cookies, defining a more consistent API. There are a few differences from the cookies:
While the cookies are accessible from both client and server side, Web Storage, in general, and Local Storage, in particular, are accessible only from client side.
Enhanced capacity (official for cookies is 4 KB) to more than 5MB per domain (Firefox, Google Chrome, and Opera and 10MB in IE).
So yes, your assumption is correct.
One thing to note about using local storage. It is very browser specific. If you store data with firefox it won't be available in chrome or ie etc. Also as far as clearing cookies and sessions, I've noticed it is also browser specific as to whether or not the local storage is cleared. I'd look into the details a lot if you're really planning on relying on local storage for an app.
Local Storage is designed to be a dependable, persistent store of data on a client. It is not designed as a "better cookie": that function is designed to be met by Session Storage.
From the Dec 2011 Web Storage Spec Candidate Recommendation,
(Local Storage) is designed for storage that spans multiple windows,
and lasts beyond the current session. In particular, Web applications
may wish to store megabytes of user data, such as entire
user-authored documents or a user's mailbox, on the client side for
performance reasons.
As client-side data - it is as persistent as any client side data, within the size limits that the browser implements. Users can delete it at any time, open it up in a text editor and edit etc. - just like ANY client side data.
If you're using localStorage for a iOS app, be very careful. THe latest version of iOS (5.1 off the top of my head) has moved localstorage and localdb data to a part of the cache that is regularly cleared, i.e. not at all persistent. I can't tell yet if this is a bug or a policy change.
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.