Protecting Authentication Tokens: Safe Storage Methods

Various methods for securely keeping authentication tokens in web browsers

Protecting Authentication Tokens: Safe Storage Methods

Introduction

Authentication tokens are cryptographic strings generated by the server and sent to the client upon successful login. Since the browser/server relationship is "stateless," there needs to be an efficient method for storing these tokens. These tokens act as proof of authentication, enabling the client to access protected resources without constantly resending login credentials. In this article, we will focus on storing JWT tokens exclusively.

Cookies are a commonly used method for storing authentication tokens on the browser. When a user logs in, the server generates a unique session ID and stores it as a cookie in the user's browser. This cookie is sent back to the server with each subsequent request, allowing the server to identify and authenticate the user. Session cookies are typically stored in memory and are deleted when the browser session ends or when the user logs out.

Let's discuss multiple ways to store tokens using cookies...

Regular Cookies

Regular cookies, also known simply as cookies, can be accessed by client-side scripts like JavaScript. They are frequently used to store user preferences, monitor user behaviour, and maintain session states between HTTP requests.

Cookies are stored in the browser's cookie storage, which can be accessed and modified by client-side scripts.

Common Attacks

Regular cookies are vulnerable to XSS, CSRF and Cookie Hijacking attacks

Pros

  1. Can be used to store custom data using client-side javascript

  2. If you need a token in a custom header, this is useful

  3. Another advantage of regular cookies is, client-side js can control when and where to send the token and reduce the risk of CSRF.

Cons

  1. Highly vulnerable to XSS and JS Injections

  2. Limited Browser storage (4096 bytes)

HTTP-only cookies are cookies that are marked with the "HttpOnly" flag in the response headers when they are set from the server. This flag indicates to the browser that the cookie cannot be accessed via client-side scripts like JavaScript.

HTTP-only cookies are included in each HTTP browser request to a server of a specific domain.

Pros

  1. Less vulnerable to XSS and JS Injections

  2. Automatically included in the request

  3. There are many options to further secure an HTTP cookie eg. Expiry, domain attribute, SameSite attribute

  4. Convenient to store a login / auth / jwt token with a specific expiry

Cons

  1. Can still be vulnerable to XSS and CSRF

  2. Limited browser storage (4096 bytes)

  3. Client Side JS cannot access even if required

The Set-Cookie HTTP response header sends cookies from the server to the user agent. A simple cookie is set like this:

This instructs the server to send headers to tell the client to store a pair of cookies:

HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

Then, with every subsequent request to the server, the browser sends all previously stored cookies back to the server using the Cookie header.

GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

LocalStorage

Local Storage is used to read and write data in the browser's storage. The data is persistent and has no expiry date. The data is stored in key-value pairs. The server has no access to the client's local storage. The client has full control on read, write, update Local Storage.

Pros

  1. Has more storage (10MB per domain)

  2. No expiry

  3. LocalStorage also works efficiently with APIs that require an access token in the header.

  4. Does not auto-included in the header. Therefore, Immune to cross-site request forgery (CSRF) attacks.

Cons

  1. Highly vulnerable to XSS

  2. An attacker can inject malicious JavaScript into a webpage, they can steal an access token in localStorage

  3. Unlike cookies, localStorage doesn’t provide secure attributes that you can set to block attacks.

Which Should You Choose?

From reading the differences and definitions this should be clear. However, to summarize it and make it even clearer:

  1. If you need to store data that is accessible for both the server and the client, use cookies. Otherwise, use local storage.

  2. If you need to store larger data, use local storage.

  3. If you need to store data that does not expire, use local storage.

  4. If you need easy-to-use methods to access and modify the data stored on the client, use local storage.

  5. If you are concerned about XSS and security, use HTTP Cookies

  6. If you want in-built options to securely store JWT-based tokens, use HTTP Cookies

  7. If you don't want a client-side script to access browser-stored data, use HTTP Cookies.