How to securely store JWT tokens - Lukasz Tkacz Blog (2024)

Last time I worked with some JWT tokens and had to resolve some issues related to security. Right now a lot of web applications and not only, because also mobile apps use these tokens to prove that we are valid and correctly logged-in users. The idea of JWT is clear, right and useful, but there are some dangerous traps during implementation on web applications. The main question is: where should we store JWT tokens to make them secure and still usable?

localStorage and sessionStorage are not good

On mobile clients, it is not a problem, because we can save them in some secure area. The thing is a bit complicated with web applications. If you already thought about this question and looked for some solutions, you probably found a lot of articles about that and some of them recommend using localStorage. During the latest years web developers got a lot of new abilities and localStorage is one of them: simple and very quick to use, it’s just something like:

// WritelocalStorage.setItem('foo', 'bar')// Readcost myValue = localStorage.get('foo')

The big additional advantage: it is persistent storage, so even if the user closes the browser and opens again, it will still be logged in. Great! So, why not, why not use it just to store our JWT token? The problem with this approach is the possibility of stealing a token using an XSS attack. XSS is an injection and execution of malicious code on a user web browser. If there is any possibility that someone will do that on your web application, then it will be possible to just execute code to steal a JWT token – because it is accessible from JavaScript level.

Of course, if we allow anyone to make an XSS attack, we have bigger problems… but think about that: in a big, complex web application, can you guarantee that there is no such possibility? We can not think in such a way and just assume that everything will be ok. The better approach is to think that everything will be bad. It is a reason why we do not have to use localStorage for JWT tokens or any sensitive data.

What about sessionStorage? It is very similar: provides a quick, easy way to store some data, but it is not persistent as localStorage. If the user open a new tab or just close and reopen the browser, there will be no data we saved. It may be good for let say banking web applications, but for most others, it will be a very bad user experience. Also, sessionStorage is still vulnerable to XSS attacks. Maybe store them just in memory? It may be a solution, but you will have additional issues with persistence, and it will be very difficult to resolve. Conclusion: such storage are not a good option.

Solution: use old school cookies

Yep, cookies come to rescue. Many people think that is old school, not used anymore. But in reality, they are still very good options in such cases. Why? First: they offer persistence. When we set cookies, we can also control expiration time. They are available in next tabs with the same web application, also after reloading and browser restart. Second: if configured correctly, they are not vulnerable for XSS attack. We can set the httpOnly flag on the cookie and after that it will not be visible from JavaScript level anymore. Wait a moment… you can ask: if it will not be available, how can we use a token from such a cookie in the authorization header?

The answer is: it will not be possible, but it is not a problem, because browsers will attach these cookies in each request and your API should just check cookies. In reality, cookies are also header, just different and process is automatic, browser will do that for you without any additional code. So, if the user has been authenticated and the API has set a proper cookie with JWT token, it will be automatically sent back, even in background (XHR, fetch) requests. So your frontend application does not have to handle that anymore.

Third: if configured correctly, it will be limited to only secure connections. Right now, all apps with public access should use secure, encrypted connections. Using a secure flag you can define that cookie should be used only on such connections, so if anyone will try to use your application on standard HTTP, such cookie will be not available and not used. Of course, you should still use different methods to provide HTTPS-only traffic: upgrade / rewrite and also send HSTS headers to inform browsers about rules for your websites.

What about CSRF/XSRF issues?

We decided to move all things to cookies, our JWT token is not vulnerable to XSS attack, and we are happy… But just for a moment, because we remembered about different attack surfaces related to cookies: CSRF. Our API sets cookies and it looks fine, but an attacker can right now just prepare a special website and command our clients to send unauthorized requests in the background. Browsers will automatically add cookies in such requests as mentioned above, so it looks like the biggest advantage is also the biggest drawback. What can you do in such a situation? The first thing is to provide strict CSRF protection: send a special token from API to the browser, then attach this token to requests and validate on API: it guarantees that only the real client (i.e. our web application) makes all requests. The problem with that option is maybe we will need to change a lot of places in our code, also handling background requests will be not easy.

Fortunately, there is a second solution, much simpler. We can add another flag to our cookies: sameSite. This option allows us to block sending cookies cross-site. Default option is “None” and it does not block anything, cross-site is possible (also with CSRF possibility). The second option is “Lax” – with such configuration browsers will not send cookies for images and frames, so it will prevent CSRF attacks. If the user clicks the URL to our website on a completely different website (or email), cookies will be added, so everything will work correctly. The latest option is “Strict”: in that case cross-site cookies are completely blocked, the most secure, but in some cases a bit limited option.

Conclusion

Use cookies to store JWT tokens – always secure, always httpOnly, and with the proper same site flag. This configuration will secure your client’s data, it will prevent XSS and CSRF attack and also should simplify web application, because you do not have to care about using tokens manually on frontend code anymore.

Set-Cookie: jwt=OUR_TOKEN_CONTENT; secure; httpOnly; sameSite=Lax;

What about refresh tokens?

Exactly the same thing – they are also super important because they allow users to generate new JWT. If you use this token to determine: is a user logged in or not, you can stop doing that. Just save such information in localStorage (simple bool) if you need. It is not a problem: if the token expires, your API will inform the frontend about unauthorized requests, and then you can call the proper service to refresh the token. If the refresh token is expired or invalid, this service will inform you about that, so you will know that the user should be redirected to the login page. Yep, all these things without using tokens manually, it will be completely transparent from web application level.

Authorization service on different domain

Bonus case: what if our authorization service is on a completely different domain or subdomain? Let’s say we use oauth.mydomain to display and handle login pages, but our users will use different websites like app.mydomain. In this scenario, cookies will not work correctly, so what can we do? There are two options. First is to move login into the app subdomain or just the main domain (then cookies will be available on all subdomains – you can still control that) – may in many cases it may be not possible or just very, very complicated because we want to support many systems. Second option: just provide a proper URL on your app and use it like a “middleware” to call authorization service, so it will be Web App ⇔ API ⇔ Authorization Service. If oauth respond with correct data, you can set proper cookies for your current domain.

How to securely store JWT tokens - Lukasz Tkacz Blog (2024)

FAQs

How to store a JWT token securely? ›

To keep them secure, you should always store JWTs inside an HttpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server. It's never accessible (both for reading and writing) from JavaScript running in the browser.

What is the safest way to store auth tokens? ›

Auth0 recommends storing tokens in browser memory as the most secure option.

Is it secure to store JWT in local storage? ›

Vulnerability to XSS Attacks: The primary security concern with Local Storage is its susceptibility to Cross-Site Scripting (XSS) attacks. If an attacker can inject malicious scripts into your web application, they can access Local Storage and retrieve the stored JWTs, leading to potential security breaches.

Is it good practice to store JWT token in database? ›

A JWT needs to be stored in a safe place inside the user's browser. If you store it inside localStorage, it's accessible by any script inside your page. This is as bad as it sounds; an XSS attack could give an external attacker access to the token.

Should I store JWT in memory? ›

You suggest storing the JWT token in memory on the client side. You're absolutely correct, Storing JWT tokens in memory on the client side is faster and gives developers more control, but it can be less secure against certain types of attacks.

How do I securely store tokens in my browser? ›

Optimal Secure Solution: Save JWT Tokens in the browser's memory and store the refresh token in a cookie
  1. Step 1: Generate and issue tokens. ...
  2. Step 2: Save the JSON web token in the browser session. ...
  3. Step 3: Save the refresh token in a secure HttpOnly Cookie. ...
  4. Step 4: How to refresh the JSON web tokens.
May 9, 2023

Is it safe to store tokens in cookies? ›

Cookies are a good option for storing tokens because they are automatically sent with every request, making it easy to authenticate requests without having to manually include the token in each request.

What is the best way to store tokens in frontend? ›

There are three common options: local storage, session storage, and cookies. Each one has its pros and cons, but none of them is completely safe from attacks. Local storage and session storage are vulnerable to cross-site scripting (XSS) attacks, where malicious scripts can access and steal your tokens.

What is more secure than JWT? ›

Secure: Opaque tokens do not contain any user information, making them more secure than JWT tokens. Flexible: Opaque tokens can be customized to store additional user information in the authorization server, which can be retrieved by the resource server when needed.

Should JWT be stored in cookie or session storage? ›

However, JWT can be stored inside Cookie. This method is safer because attackers won't be able to steal your user's token easily. It's also important to know that cookies are not immune to attacks, more security measures should be implemented for the overall security of the application.

What prevents a JWT from being tampered with? ›

Use an encrypted channel(HTTPS): Encrypting data while it's in transit between the client and server when sending JWTs over HTTPS ensures confidentiality and integrity. By using HTTPS, attackers are prevented from listening in on or altering the JWTs while they are being transmitted.

What is the best way to store JWT tokens? ›

Use cookies to store JWT tokens – always secure, always httpOnly, and with the proper same site flag. This configuration will secure your client's data, it will prevent XSS and CSRF attack and also should simplify web application, because you do not have to care about using tokens manually on frontend code anymore.

How to implement JWT securely? ›

Best Ways to Securely Implement JWTs
  1. Use strong algorithms like HMAC-SHA256 or RSA to sign and encrypt your tokens. ...
  2. Set an expiration time for the JWT to limit its validity period. ...
  3. Set refresh token features to extend the session duration, which allows users to fetch new JWT tokens for an extended period of time.

What is the JWT secret? ›

A JWT consists of a header, payload, and a digital signature. The header and payload are base64url-encoded and are used with a secret key to generate a digital signature. The server sends the JWT to the browser after user authentication.

How can JWT be prevented from being stolen? ›

Preventive steps by aircraft owners should include the following: (1) store the aircraft in a locked hanger or park it in a well-lighted and secure area; (2) use metal aircraft tiedown straps of sufficient strength to discourage cutting; (3) install antitheft devices, such as wheel locks; (4) complete a list of all ...

How to encrypt a JWT token? ›

Encrypting a JWT for a given recipient requires their public RSA key. The decryption takes place with the corresponding private RSA key, which the recipient must keep secret at all times. To create an RSA encrypter with Nimbus JOSE+JWT for a given public key: JWEEncrypter encrypter = new RSAEncrypter(rsaPublicKey);

How do I store API tokens safely? ›

Avoid Client-Side Exposure

Storing API keys in client-side code such as JavaScript is an insecure practice as it makes them easily accessible to malicious actors. To ensure the security of your API keys, never embed them in URLs or client-side code. Instead, keep them securely stored server-side to protect your data.

Can a JWT token be hijacked? ›

It is used literally everywhere: from sessions to token-based authentication in OAuth, to custom authentication of all shapes and forms. There is actually a pretty good reason for this wide adoption and that is, for the most part, security and resilience. However, just like any technology, JWT is not immune to hacking.

Top Articles
Freight damage claims FAQs
Top 7 World’s Most Advanced AI Systems : 2024
Xre-02022
Team 1 Elite Club Invite
Deshret's Spirit
Rainfall Map Oklahoma
Grand Park Baseball Tournaments
Find your energy supplier
Power Outage Map Albany Ny
The Connecticut Daily Lottery Hub
Craigslist Pets Sac
Pittsburgh Ultra Advanced Stain And Sealant Color Chart
Hartland Liquidation Oconomowoc
2016 Hyundai Sonata Refrigerant Capacity
Spectrum Field Tech Salary
Craighead County Sheriff's Department
Nesz_R Tanjiro
Jellyfin Ps5
How to Watch the Fifty Shades Trilogy and Rom-Coms
Dover Nh Power Outage
Nearest Walgreens Or Cvs Near Me
The Ultimate Guide to Extras Casting: Everything You Need to Know - MyCastingFile
All Obituaries | Gateway-Forest Lawn Funeral Home | Lake City FL funeral home and cremation Lake City FL funeral home and cremation
Colonial Executive Park - CRE Consultants
Doctors of Optometry - Westchester Mall | Trusted Eye Doctors in White Plains, NY
Remnants of Filth: Yuwu (Novel) Vol. 4
Taylored Services Hardeeville Sc
Mobile crane from the Netherlands, used mobile crane for sale from the Netherlands
Mia Malkova Bio, Net Worth, Age & More - Magzica
Wells Fargo Bank Florida Locations
Gus Floribama Shore Drugs
La Qua Brothers Funeral Home
Craigslist Cars And Trucks Mcallen
Renfield Showtimes Near Marquee Cinemas - Wakefield 12
Why Are The French So Google Feud Answers
ShadowCat - Forestry Mulching, Land Clearing, Bush Hog, Brush, Bobcat - farm & garden services - craigslist
Tamilrockers Movies 2023 Download
Garrison Blacksmith's Bench
2012 Street Glide Blue Book Value
Stanford Medicine scientists pinpoint COVID-19 virus’s entry and exit ports inside our noses
Craigslist Ludington Michigan
Htb Forums
Obituaries in Hagerstown, MD | The Herald-Mail
Jetblue 1919
Streameast Io Soccer
Tropical Smoothie Address
The Largest Banks - ​​How to Transfer Money With Only Card Number and CVV (2024)
Hughie Francis Foley – Marinermath
Urban Airship Acquires Accengage, Extending Its Worldwide Leadership With Unmatched Presence Across Europe
Diablo Spawns Blox Fruits
La Fitness Oxford Valley Class Schedule
Latest Posts
Article information

Author: Dong Thiel

Last Updated:

Views: 5599

Rating: 4.9 / 5 (79 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Dong Thiel

Birthday: 2001-07-14

Address: 2865 Kasha Unions, West Corrinne, AK 05708-1071

Phone: +3512198379449

Job: Design Planner

Hobby: Graffiti, Foreign language learning, Gambling, Metalworking, Rowing, Sculling, Sewing

Introduction: My name is Dong Thiel, I am a brainy, happy, tasty, lively, splendid, talented, cooperative person who loves writing and wants to share my knowledge and understanding with you.