Why Do We Need Refresh Token? Do You Know How to Securely Store Refresh Token and Access Token in the Browser? Part 2

Why Do We Need Refresh Token? Do You Know How to Securely Store Refresh Token and Access Token in the Browser? Part 2

Daily short news for you
  • People often joke that regex is the language of aliens. Anyone who can write regex has the abilities of an extraterrestrial. It's just a joke, but the truth is that regex is really hard to understand.

    By chance, I came across a website that teaches us regex step by step. During the learning process, we need to interact with dozens of questions ranging from simple to advanced in order to gradually learn how to use this "alien language".

    regexlearn.com

    » Read more
  • Good news to start the day. GitHub has just widely announced GitHub Models to everyone. If you remember, more than 2 months ago, GitHub had a trial program for using LLMs models, and in my case, it took a month to get approved for use. Now, they have given everyone with a GitHub account access, no registration needed anymore 🥳

    GitHub Models is currently a lifesaver for me while building this blog 😆

    GitHub Models is now available in public preview | Github Blog

    » Read more
  • I came across a repository that uses Tauri and Svelte to rewrite an application like the Task Manager on Windows or the Monitor on Mac. I was curious, so I downloaded it and was surprised to find that the app is only a few MB in size and loads quickly. The app itself is also very smooth

    » Read more

The Issue

See previous part: Why Do We Need Refresh Token? Do You Know How to Securely Store Refresh Token and Access Token in the Browser?.

In the previous article, we learned about why we should use Refresh Token. The issue at hand is that if the Access Token is stolen, there is a high chance that the Refresh Token will also be compromised. So what's the point of generating a Refresh Token when the possibility of losing both is the same?

To find the answer to this issue, many debates have emerged and it seems that there is no definitive conclusion because everyone has valid points. I play the role of an audience sitting in the stands of a football field, absorbing their opinions and synthesizing them to provide the most satisfactory answer. Of course, it is not entirely accurate and I hope readers can find any inconsistencies in it.

Where to Store Refresh Token?

Where to Store Refresh Token?

My final answer is "in the browser." Depending on the level of security you aim for, you can choose the most suitable option to save time and cost. Inside the browser, there are several storage methods such as Cookies, localStorage, sessionStorage, and even a server-side storage called Session. Each method has its own business logic, and cleverly organizing the storage of Access Token and Refresh Token in it helps minimize the severity of XSS attacks.

A fact is that if your website is attacked by XSS, regardless of where you store them, the chances of Access Token and Refresh Token being leaked are high. To make it easier to understand, let's dissect the nature of an XSS attack. An XSS attack occurs when the attacker can run JavaScript code on your website. This means that the attacker can retrieve the access token stored anywhere the JavaScript code has access to. An XSS attack can occur through third-party JavaScript code in your website, such as React, Vue, jQuery, Google Analytics, etc. The more popular the library, the greater the attention it attracts, and once it is compromised, the damage can be enormous.

It is clear that not using any third-party library in your website is very difficult. Every library added increases the risk. Attackers can also exploit XSS through form/input fields on your website. For example, a public chat feature can be vulnerable to a JavaScript code that steals data. If the display of chat content is not properly handled, other users accessing the website can easily get infected. A MIME sniffing attack can also result in an XSS attack.

Parallel to XSS is a CSRF (Cross-Site Request Forgery) attack targeting the Access Token. It is understood as an attack that forces the user to perform unintended requests. The attacker does not directly steal the Access Token or Refresh Token but takes advantage of the Access Token attached to each request to the server.

For example, a website allows users to change their email through an API:

POST /email/change HTTP/1.1 
Host: yoursite.com 
Content-Type: application/x-www-form-urlencoded 
Cookie: sessionID=qwerty 

[email protected]

The attacker creates an automatic form that sends a POST request to /email/change with their email attached. At that time, the session will be automatically added to the request because you are directly accessing the website, but you are unaware of the presence of that hidden form. However, this can be minimized by using `sameSite`.

From there, it can be concluded that in order to prevent the leakage of Access Token and Refresh Token, they must be stored in a location where JavaScript code has no access. Is there such a place in the browser? Yes, there is, and it is the `httpOnly` cookie. But is httpOnly the ultimate solution? Before answering, I want you to have a clearer understanding of common storage mechanisms in browsers and servers.

Session Cookie

Session is one of the most commonly used ways to identify user sessions in server-side render web applications. The working mechanism is quite easy to understand. The server generates a session ID for each request to identify the session, the browser saves that ID and sends it along with all subsequent requests.

This method requires the server to store and manage sessions for each client. The session ID is typically stored by the client in a Cookie or as a parameter in the URL. This still makes it susceptible to being stolen through an XSS attack.

Cookie

No need to say much, a Cookie is information stored on your computer by a website you visit. It is used to store information you need on a website, such as user login information... Cookies have been one of the oldest methods used for this purpose. The information stored in a Cookie is sent to the server through request headers, allowing the server to identify the user's session.

JavaScript has access to Cookies, so they can still be stolen by an XSS attack.

However, there is a concept called httpOnly for Cookies. If a cookie has the additional httpOnly option specified, it is immune to JavaScript. This means that JavaScript does not have access to the httpOnly cookie, and it is automatically sent with each request to the server.

localStorage and sessionStorage

These are two storage methods with much larger capacity than Cookies. Therefore, they are often used to store large amounts of information or as cache memory for website features to ensure smooth performance.

Information in localStorage is persistently stored until you delete it. On the other hand, sessionStorage is usually cleared after you end your session with the website (close tab, close browser...).

JavaScript has access to both, so they can still be stolen by an XSS attack.

From there, it can be concluded that there are different ways to store:

  • Storing Access Token and Refresh Token in localStorage or cookie -> susceptible to CSRF, stolen through XSS.
  • Storing both in httpOnly cookie -> vulnerable to CSRF, but can be mitigated. Better than the first option.
  • Storing only Refresh Token in httpOnly cookie -> safe from CSRF. Although the Access Token could be stolen, it only exists for a short time, so the risk can be minimized.

It can be seen that the third method is more advantageous than the first two methods. Setting it up is not too complicated. Just when logging in or authorizing, the Access Token is returned in the response body, while the Refresh Token is only returned through the httpOnly cookie.

That's the storage method to minimize the leakage of Access Token and Refresh Token. In case Access Token and Refresh Token are leaked, is there any way to detect or prevent it? I will continue with another article in this series. Thank you for following along.

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.
Author

Hello, my name is Hoai - a developer who tells stories through writing ✍️ and creating products 🚀. With many years of programming experience, I have contributed to various products that bring value to users at my workplace as well as to myself. My hobbies include reading, writing, and researching... I created this blog with the mission of delivering quality articles to the readers of 2coffee.dev.Follow me through these channels LinkedIn, Facebook, Instagram, Telegram.

Did you find this article helpful?
NoYes

Comments (4)

Leave a comment...
Avatar
Nguyen Danh4 months ago
PA2 - Lưu trữ cả hai trong httpOnly cookie -> dễ bị CSRF nhưng có thể tránh được. PA3 - Chỉ lưu trữ Refresh Token trong httpOnly cookie -> an toàn khỏi CSRF. Vì sao đều lưu ở httpOnly cookie nhưng PA2 thì dễ bị CSRF còn PA3 thì an toàn ???
Reply
Avatar
Trần Ngọc Hải1 year ago
Thật ra ko thể tránh khỏi việc dữ liệu bị đánh cắp cốt là cách xử lý sau khi bị đánh cắp như thế nào cho giảm thiểu tối đa rủi ro
Reply
Avatar
Nguyễn Văn Nhật1 year ago
M có đọc được lời khuyên là nên lưu vào bộ nhớ ứng dụng ví dụ như reduce hoặc một biến nào đó khởi tạo trong ứng dụng. Ví dụ như là const token = 'xxx'
Reply
Avatar
Xuân Hoài Tống1 year ago
Người dùng vẫn có thể đột ngột tắt trình duyệt hoặc hệ điều hành cũng có quyền kết thúc tiến trình thế nên bạn sẽ không kịp lưu lại được
Avatar
Nguyễn Văn Nhật1 year ago
Trước khi reload mình sẽ lưu lại vào localStorage, nó giống như kiểu hiện 1 alert khi bấm vào reload vậy
Avatar
Xuân Hoài Tống1 year ago
Ý bạn là redux? Đúng vậy bạn có thể lưu lại AT hoặc RT vào đó nhưng nếu reload lại page thì sẽ bị mất và người dùng phải đăng nhập lại
Avatar
Long Domi1 year ago
H mới chịu ra cơ mà e muốn hỏi chổ CSRF kia là ntn ạ hơi khó hiểu
Reply
Avatar
Long Domi1 year ago
@gif [tfUW8mhiFk8NlJhgEh] Trả lời bình luận có cả email luôn ghê thật 
Avatar
Long Domi1 year ago
Thanks a e sẽ nghiên cứu ạ
Avatar
Vũ Mạnh Đức1 year ago
CSRF là một cuộc tấn công giả mạo người dùng, bạn có thể đọc thêm trên google hoặc https://developer.mozilla.org/en-US/docs/Glossary/CSRF. Đại loại là kẻ tấn công lợi dụng chính những request từ máy bạn để vượt qua được xác thực (bởi vì các request được gửi từ máy bạn) để thực hiện hành vi yêu cầu quyền xác thực. Những hành vi đó có thể gây nguy hiểm như đổi mật khẩu, đổi email...