-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of github.com:supertokens/blog into sitemaps-ex…
…periments
- Loading branch information
Showing
12 changed files
with
325 additions
and
27 deletions.
There are no files selected for viewing
104 changes: 104 additions & 0 deletions
104
content/cookies-vs-localstorage-for-sessions-everything-you-need-to-know/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
--- | ||
title: Cookies vs Localstorage for sessions–everything you need to know | ||
date: "2020-06-23" | ||
description: "Learn about the best approach and common misconceptions of storing sessions in cookies or browser storage" | ||
cover: "cookies-vs-localstorage-for-sessions-everything-you-need-to-know.png" | ||
category: "sessions" | ||
author: "Rishabh Poddar" | ||
--- | ||
|
||
For logged-in users, session tokens act as a proxy to their identity. These tokens (JWT or non-JWT) are issued by the backend and sent to the frontend where they are stored. If they are misused or stolen, the attacker can gain unauthorized access to the victim’s account. As such, we must make sure to **minimize the risk of all the possible ways a session attack can be carried out.** | ||
|
||
One of the session attack vectors is the frontend client – the web browser. The session tokens are stored here for as long as the user is logged in. This means we must be careful about where and how we store them. This is where we start to consider the debate of browser storage (localstorage, sessionstorage etc..) vs cookie storage. | ||
|
||
Before we get into the pros and cons of the two storage types, let’s examine their properties briefly. | ||
|
||
_A clarification point: Both JWT and non-JWT (opaque) session tokens can be stored in cookie storage or in browser storage. The only difference between the two types is the amount of space they take up, which we will consider in this article. But apart from this difference, when we refer to “session token”, we mean either of the two types._ | ||
|
||
## Storage properties | ||
|
||
The table below compares the different storage mechanisms across all the various relevant properties. Note that ‘browser storage’ can actually be either local or session storage, IndexedDB or Web SQL. | ||
|
||
![Property Comparision Table](./property-comparision-table.png) | ||
|
||
Session storage <span style="color:red;font-family:Montserrat,sans-serif" >**X**</span> - Most apps require the user to be logged in even if they open multiple browser tabs or restart the browser and hence we can eliminate this method of storage (don’t be deceived by its name). | ||
|
||
IndexedDB <span style="color:red;font-family:Montserrat,sans-serif" >**X**</span> – Session tokens are key-value pairs. As such, they do not need complex querying capabilities. Using IndexedDB can technically be an option, however, it would be more complex than using localstorage for the purposes of storing and retrieving session tokens. | ||
|
||
Web SQL <span style="color:red;font-family:Montserrat,sans-serif" >**X**</span> - Looking at the table, it is clear that WebSQL was never an option. | ||
|
||
We are left with choosing between localstorage and Cookie storage. | ||
|
||
## Cookies vs Localstorage | ||
|
||
We will compare these storage types from a usability and security point of view. For usability, we will consider ease of writing, reading and deleting session tokens, and any limitations placed by each of the storage types for specific use cases. | ||
|
||
From a security point of view, we will consider the different methods that can be used for token misuse or theft for each of the storage types. | ||
|
||
## Usability analysis | ||
|
||
1. <u>Size constraints</u>: Cookies have a size limitation of 4kb per domain, whereas localstorage size is an order of magnitude larger. For most cases, 4kb is more than enough for storing session tokens, even when using JWTs[_[1]_](/blog/cookies-vs-localstorage-for-sessions-everything-you-need-to-know#footer-note-1). | ||
|
||
**Cookie: 1; Localstorage: 1** | ||
|
||
2. <u>Automatic management</u>: Cookies are automatically saved, sent and removed by the browser. The frontend developer does not have to worry about implementing this part, nor is there any scope of a mistake from the frontend side. This is not true for localstorage. | ||
|
||
**Cookie: 2; Localstorage: 1** | ||
|
||
3. <u>Server side rendered apps</u>: When doing browser level navigation (user types in a URL into their browser / opens a link on a new tab), only cookies are sent. This means, for those API calls to the server, they will only get the session tokens if they are using cookies – localstorage will not work. | ||
|
||
**Cookie 3; Localstorage 1** | ||
|
||
4. <u>Sharing the same session across subdomains</u>: The objective here is that the user should use the same session when navigating to different subdomains of a site. This can be easily done via cookies by setting the cookie domain as “.yoursite.com”. <br/> This is not easily possible to do via localstorage since the store is not shared across domains / subdomains. One can use iframes to hack around this, however it’s non trivial. | ||
|
||
**Cookie: 4; Localstorage: 1** | ||
|
||
## Security Analysis | ||
|
||
1. <u>Token misuse via XSS attack</u>: An XSS attack happens when “malicious” JavaScript is injected into a website. Some ways in which this code injection can happen are incorrect input / output validation, a rogue third party script being loaded into the site’s frontend code or social engineering. | ||
|
||
If using localstorage, the malicious JS code can easily read the session tokens and transmit them to the attacker. The attacker would then put these tokens into their browser and have significant, if not complete access to that user’s account. | ||
|
||
Cookies have this special flag called httpOnly. If set, it prevents any JS on the frontend from reading that cookie’s value. This means that the malicious JS code cannot send the access token to the attacker. However, that code can still do malicious API calls while the user is using the site. Depending on the product and the reason for the attack, that may not be enough to fulfill the attacker’s intention. | ||
|
||
**Cookie: 5; Localstorage: 1** | ||
|
||
2. <u>Token misuse via CSRF attack</u>: This is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. This unwanted action is performed when a user visits a third party malicious site. This attack is only possible if using cookies to store access tokens. However, it can also be easily mitigated using anti-csrf tokens or the sameSite flag in cookies. Regardless, when using localstorage, one does not need to think about this attack vector. | ||
|
||
**Cookie: 5; Localstorage: 2** | ||
|
||
3. <u>Token theft via a malware</u>: This is a growing concern. In fact, many large Youtube subscribers’ accounts were hijacked because their session tokens were stolen via a malware on their computer. They were infected with this malware due to a social engineering attack. Neither localstorage, nor cookie storage will make a difference to mitigate this attack (hence no points awarded to either). The only measure one can take here is to have [token theft detection](https://datatracker.ietf.org/doc/html/rfc6819#section-5.2.2.3) in place. | ||
|
||
**Cookie: 5; Localstorage: 2** | ||
|
||
## Misconceptions | ||
|
||
1. <u>Cookies can be cleared by the user</u>: This is true, however, the same holds for localstorage as well. When clearing browsing history and cookies, localstorage is also cleared. | ||
|
||
2. <u>No need for cookie consent when using localstorage</u>: A site only needs to ask for cookie consent for cookies that are not “strictly necessary cookies” (learn more about it [here](https://gdpr.eu/cookies/)). Session cookies count as strictly necessary and hence a user cannot deny their usage. That being said, the user still needs to be told about their existence. | ||
|
||
3. <u>Mobile apps cannot use cookies</u>: This is simply not true. All mobile development frameworks (iOS, Android, React Native, Flutter, Cordova, etc..) have native support for cookies. | ||
|
||
## Conclusion | ||
|
||
Based on the final scores (Cookie: 5; Localstorage: 2), it’s quite clear that httpOnly, secure cookies is the right way to go for storing session tokens. This is also a recommendation from the OWASP community[_[2]_](/blog/cookies-vs-localstorage-for-sessions-everything-you-need-to-know#footer-note-2). | ||
|
||
This article is written by the team at [SuperTokens](/blog) – we are building a session management solution that optimizes for security, developer, and end-user experience. If you liked this article, you may also be interested in: | ||
|
||
- [Are you using JWTs for user sessions in the correct way?](/blog/are-you-using-jwts-for-user-sessions-in-the-correct-way) | ||
- [The best way to securely manage user sessions](/blog/the-best-way-to-securely-manage-user-sessions) | ||
|
||
## Footnotes | ||
|
||
[1]: A typical JWT contains the following information: | ||
- iss (issuer): site name (20 bytes is a good upper limit) | ||
- sub (subject): 36 bytes UUID | ||
- aud (audience): site name (20 bytes is a good upper limit) | ||
- exp (expiry): timestamp: 13 bytes | ||
- nbf (not before time): timestamp: 13 bytes | ||
- iat (issued at time): timestamp: 13 bytes | ||
- custom roles and information: 200 bytes more | ||
|
||
This is a total of 315 bytes. The JWT header is normally between 36 and 50 bytes and finally the signature is between 43 and 64 bytes. So this gives us a maximum of 429 bytes which would take about 10% of cookie space. | ||
|
||
[2]: *“Do not store session identifiers in localstorage as the data is always accessible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.”* [Source](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html) |
Binary file added
BIN
+108 KB
...storage-for-sessions-everything-you-need-to-know/property-comparision-table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
--- | ||
title: How we cut our AWS costs by more than 50% | ||
date: "2023-09-19" | ||
description: "Part 1 in a series of how we were able to cut down our AWS infrastructure costs by more than 50%" | ||
cover: "how-we-cut-our-aws-costs.png" | ||
category: "programming" | ||
author: "Joel Coutinho" | ||
--- | ||
|
||
In this two part series we will go over SuperTokens manged service infrastructure and the changes we made to cut our AWS billing by more than 50%. | ||
|
||
**Part 1: How does the SuperTokens managed service work and why does it need to change.** | ||
|
||
## Introduction | ||
|
||
The SuperTokens managed service powers numerous web products, mobile applications, and services and is primarily hosted on AWS. Our infrastructure leverages a suite of AWS tools, including AWS RDS for our database, EC2 instances for SuperToken deployments, and System Manager for instance management and automation. Over time, we've refined our deployment cycle to enhance stability, fault tolerance, and cost efficiency but our most recent update has yielded our biggest savings yet, slashing costs by over 50% while achieving [record scalability](https://twitter.com/supertokensio/status/1701600309397852270). | ||
|
||
|
||
## What was the SuperTokens infrastructure like? | ||
|
||
To gain a better understanding of the SuperTokens infrastructure, it's crucial to grasp the deployment cycle. | ||
|
||
![SuperTokens Deployment process](./supertokens-deployment-process.png) | ||
|
||
SuperTokens allow users to use the SuperTokens SAAS service in two modes: development and production. Here’s the breakdown of each: | ||
|
||
**Development Mode:** | ||
The Development mode runs on an *EC2 T3.small* instance. To maximize resource utilization, we deploy up to seven development core instances on the same *T3.small* instance. This configuration results in a remarkably swift setup for new development cores, typically taking a mere 15-20 seconds and is suitable for testing purposes. | ||
|
||
**Production mode:** | ||
In contrast, production mode follows a different deployment strategy. Each production mode deployment is hosted on a dedicated *EC2 T2.micro* instance. This means that when a new production SuperTokens core instance needs to be created, a fresh *T2.micro* instance is spun up, and docker is installed on it using System Manager. Consequently, this process requires additional time compared to the development mode, with an average deployment time of around 4-5 minutes. | ||
|
||
|
||
For example, if 7 users were to sign up for SuperTokens, it would look like the following: | ||
|
||
![SuperTokens example Infrastructure](./supertokens-example-infrastructure.png) | ||
|
||
### Initial Improvements to the deployment cycle | ||
|
||
One of our initial optimizations focused on reducing the startup time for generating production instances. We recognized that creating a custom [AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)(Amazon Machine Image) pre-installed with Docker alongside the operating system that would cut down on start-up time. This change trimmed approximately 45 seconds from the production deployment procedure, reducing the setup time to approximately 3-4 minutes. | ||
|
||
In retrospect, another avenue for improvement that we identified was the usage of [AWS Reserved Instances](https://aws.amazon.com/ec2/pricing/reserved-instances/). While this approach would have entailed an upfront cost, it would have resulted in substantial long-term savings. | ||
|
||
So what prompted us to change our deployment process? | ||
|
||
## Why we had to change our deployment process | ||
The past year has been quite a ride for SuperTokens. We released a host of new features and saw a big uptick in users. But, as our user numbers climbed, so did our infrastructure costs. With our AWS credits running out soon, we knew we had to do something to cut our expenses. | ||
|
||
With the release of our new multi-tenancy feature we saw the opportunity to consolidate core instances to optimize the utilization of our EC2 instances to cut down our costs while also providing the expected performance. | ||
|
||
In part 2 we will go over the changes we made to achieve this. | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+50.8 KB
content/how-we-cut-our-aws-costs/supertokens-example-infrastructure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.