Skip to content

Commit

Permalink
Merge branch 'master' of github.com:supertokens/blog into sitemaps-ex…
Browse files Browse the repository at this point in the history
…periments
  • Loading branch information
Chakravarthy7102 committed Sep 25, 2023
2 parents 837ca06 + 1b7fb4a commit 3a7829c
Show file tree
Hide file tree
Showing 12 changed files with 325 additions and 27 deletions.
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)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions content/how-we-cut-our-aws-costs/index.md
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions content/http-error-codes-401-vs-403/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ category: "programming"
author: "Joel Coutinho"
---

## Table of content
## Table of contents
- [Introduction](#introduction)
- [HTTP 401 UNAUTHORIZED](#http-401-unauthorized)
- [HTTP 403 FORBIDDEN](#http-403-forbidden)
Expand All @@ -16,7 +16,7 @@ author: "Joel Coutinho"

## Introduction

Understanding HTTP status codes is imperative since most modern Web APIs leverage this protocolr and on the surface, HTTP status codes are straightforward. A `200` response signifies the request was successfully completed while a `404` signifies that the address was not found and a `500` means an internal error occurred in the backend server. But there seems to be some confusion between error codes `401 Unauthorized` and `403 Forbidden`. In this blog we will be looking into the differences between the two and when is it appropriate to respond with them.
Understanding HTTP status codes is imperative since most modern Web APIs leverage this protocol and on the surface, HTTP status codes are straightforward. A `200` response signifies the request was successfully completed while a `404` signifies that the address was not found and a `500` means an internal error occurred in the backend server. But there seems to be some confusion between error codes `401 Unauthorized` and `403 Forbidden`. In this blog post, we will explore the distinctions between the two error codes and provide insights into the specific scenarios where each error code is applicable.

## HTTP 401 UNAUTHORIZED
The HTTP status code 401, often denoted as `UNAUTHORIZED`, signifies that the client lacks proper authentication credentials or has provided invalid credentials. In simpler terms, the server has failed to identify the user.
Expand Down Expand Up @@ -48,6 +48,6 @@ While both HTTP error codes indicate access denial, their fundamental difference
## Conclusion

To summarize the main difference between the two, although both status codes represent access denial, 401 errors address authentication issues, and 403 errors point towards authorization problems.
It is important to make this distinction as incorrectly handling these responses can leave you suspectable to exploits from malicious attackers.
It is important to make this distinction as incorrectly handling these responses can leave you susceptible to exploits from malicious attackers.


Loading

0 comments on commit 3a7829c

Please sign in to comment.