Documentation

/

White Papers

Secure Login Token Management: An Essential Frontend Strategy

zac

November 22, 2024

Secure Login Token Management: An Essential Frontend Strategy

Introduction

In today’s technological landscape, user authentication methods are constantly evolving, and security protocols are advancing accordingly. Token-based authentication, known for its high scalability and flexibility, is rapidly becoming the standard. This method is increasingly replacing traditional session-based authentication due to its enhanced security and efficiency. QueryPie has also adopted token-based authentication in its products to improve security.

New Challenges in the Frontend Domain

The history of implementing authentication in the web frontend is relatively short. Traditional session-based authentication relies on the server to manage user sessions. In the frontend, authentication was once as simple as creating a form and transmitting the user’s ID and password to the server’s designated endpoint. However, in recent years, the frontend landscape has experienced several significant technological changes.

  1. Thanks to the rise of AJAX and Single Page Application (SPA) architecture, frontend developers now exchange data with the backend using JSON-based API communication.

  2. With the advent of the Web Storage API, managing persistence in the frontend has become much easier.

  3. Additionally, the emergence of SSR (Server-Side Rendering) frameworks like NextJS has shifted many roles previously handled by the server to the frontend.

These changes, when combined with token-based authentication, present the frontend with a new challenge: secure token transmission and persistence management.

Secure Tokens and the Risk of Insecure User Environments

Token-based authentication is not only convenient for developers but also provides strong security due to its resistance to tampering. However, the situation changes if the token itself is compromised.

Types of Threats

The primary route for token theft is through the user's browser. If a user is using an outdated browser, it may be vulnerable to exploits targeting browser vulnerabilities. Recently, the rise of evergreen browsers like Chrome, which ensures users are always using the latest version, has led to quicker patching of browser vulnerabilities.

However, the more likely weak points lie in JavaScript code that does not meet the security standards provided by the browser or in incorrect server configurations. Attackers can exploit these vulnerabilities to perform attacks such as Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), or Session Hijacking, leading to token theft or similar types of attacks.

Cross Site Scripting (XSS)

https://owasp.org/www-community/attacks/xss/

Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it.

An XSS (Cross-Site Scripting) attack involves executing malicious scripts in the user's browser, which is a traditional form of code injection. While there are various methods of attack, the most common example is as follows:

  • The attacker identifies a vulnerability in the website, for example, a search parameter on a URL like vulnerable-site.com/search?query=${query}, where the query parameter is directly output to the results page without proper sanitization.

  • The attacker then injects malicious code into the query string, such as: vulnerable-site.com/search?query=<script>...malicious code...</script> The result is that the malicious script is executed when the search results page is loaded, and the link containing the malicious code is included in the page.

  • The attacker then shares this link through messengers, communities, or other platforms, encouraging other users to click on it.

  • If the site allows JavaScript to access the user's session or access token, the attacker could steal the access token, exposing the user to token theft.

Cross Site Request Forgery (CSRF)

https://owasp.org/www-community/attacks/csrf

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.

A CSRF (Cross-Site Request Forgery) attack by itself doesn't directly steal tokens, but similar to an XSS attack, it exploits weaknesses in website design and user authentication states, causing users to unintentionally perform actions that could lead to malicious consequences. This can be just as critical a vulnerability as token theft.

  1. The attacker sends a phishing email that appears to come from a legitimate site (e.g., vulnerable-shop.com) and tricks the user into clicking on a link that redirects to a malicious website (e.g., scam-shop.com).

  2. If the user is already logged in to vulnerable-shop.com, clicking the link takes them to scam-shop.com.

  3. The malicious scam-shop.com page contains a script that automatically executes as soon as the page is loaded.

123456789
<form id="form" action="https://vulerable-shop.com/api/purchase" method="POST">    <input type="hidden" name="item_id" value="$expensive_item">    <input type="hidden" name="address" value="$attackes_house">    <input type="hidden" name="amount" value="10000">    <button type="submit">Purchase</button></form><script>    document.getElementById('form').submit();</script>

If the user is already logged in and the security settings are inadequate, the attacker can trick the user into unknowingly purchasing 10,000 expensive items and sending them to the attacker.

A CSRF attack exploits the nature of cookies, which operate as follows:

  • Cookies are stored in the user's browser.

  • Cookies are automatically included in any request made to the domain specified in the cookie settings.

Frontend Authentication Security: Best Practices and Threat Analysis with QueryPie RED Team

Implementing authentication securely is notoriously challenging. It requires not only delivering robust functionality but also addressing potential security vulnerabilities. While developing QueryPie, a security solution, the frontend team devoted significant effort and research to integrating reliable authentication mechanisms. Throughout this process, QueryPie's RED Team played a pivotal role by conducting white-hat hacking on our products, uncovering potential vulnerabilities, and helping us enhance our authentication framework to build a more secure system.

As mentioned earlier, implementing secure authentication in frontend development remains a relatively immature field. Many guides available online suggest practices that are actually security-compromised, making it difficult to identify accurate and reliable information.

In this article, we will explore the types of threats present in frontend code written by developers at QueryPie. Through concrete examples, we will diagnose common vulnerabilities and present best practices to address these issues. By the end of this article, you’ll feel confident in implementing authentication securely in frontend applications without unnecessary concerns.

Example: Beginner Frontend Developer's SPA Authentication Implementation

Below is a commonly seen code snippet for login and API requests in Single Page Applications (SPA):

12345678910111213141516171819
async function login(id, pw) {    const res = await fetch('<cross_origin_api_url>/api/auth', {        method: 'POST',        body: encrypt({id, pw}),        mode: 'cors'    });    const token = await res.json();    localStorage.setItem('accessToken', token.accessToken);} async function getProtectedResource(id) {    const accessToken = localStorage.getItem('accessToken');    const res = fetch(`<cross_origin_api_url>/api/protected-resource/${id}`, {        headers: {            Authorization: `Bearer ${accessToken}`        },        mode: 'cors'    });}

The code has the following context:

  1. API Agreement with the Backend

  • Tokens are included in the Authorization header for authentication.

  • Access-Control-Allow-Origin header is set to * to allow all origins, for development convenience.

  1. Token Persistence

  • The localStorage API is used to store tokens for reuse across user sessions.

Based on the provided code and its context, the following threats are exposed:

Authorization Header → Vulnerable to XSS Attack

Using the Authorization header to send the access token can be vulnerable to XSS attacks. For tokens to be included in the Authorization header, they must be stored in either JavaScript memory or some form of storage. If an attacker successfully executes an XSS attack, they gain access to the page's JavaScript environment. Any globally exposed tokens or functions to retrieve tokens can be accessed and subsequently stolen by the attacker.