Localstorage + JWT

Hello! So I am currently working on a project where I want to store a JWT Token in localstorage... But I am having some issues finding out how I can use it? Is there a better way than storing it in the localstorage, and how would I store it in the localstorage?
11 Replies
Nasr galal
Nasr galal6mo ago
May I ask which Auth module are you using? 🙂
StilauGamer
StilauGamerOP6mo ago
I am not using any, fully custom 😅
Nasr galal
Nasr galal6mo ago
oh interesting! so in Server side, we could use the localStorage.setItem('set_name_token_here') method, this should save the token in a key-pair value and if you like to get the stored token, just use localStorage.getItem('the-name-we-specified-before') ---- If you care about security, here are few other alternative approaches you may look into: 1. Session Storage: provides temporary storage for data specific to a browser tab or window. Data is cleared when the user closes the tab or window. Implementation:
// services/auth.js (updated)
const token = sessionStorage.getItem('auth_token');
sessionStorage.setItem('auth_token', token);
sessionStorage.removeItem('auth_token');
// services/auth.js (updated)
const token = sessionStorage.getItem('auth_token');
sessionStorage.setItem('auth_token', token);
sessionStorage.removeItem('auth_token');
2. Cookies: They are small pieces of data sent from the server to the user's browser and stored locally. They are often used for session management and can be configured with specific expiration times and security flags like HttpOnly. Implementation (requires backend integration to set and retrieve cookies):
// services/auth.js (updated)
const token = document.cookie.split(';').find(c => c.startsWith('auth_token='));
// Set cookie on login from backend response
document.cookie = `auth_token=${token}; HttpOnly; Path=/`; // Assuming backend sets the cookie
document.cookie = 'auth_token=; expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/'; // Clear cookie
// services/auth.js (updated)
const token = document.cookie.split(';').find(c => c.startsWith('auth_token='));
// Set cookie on login from backend response
document.cookie = `auth_token=${token}; HttpOnly; Path=/`; // Assuming backend sets the cookie
document.cookie = 'auth_token=; expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/'; // Clear cookie
3. IndexedDB: It is a more robust client-side database that allows structured data storage with indexes for efficient retrieval. It's suitable for storing larger amounts of user data or complex objects. Implementation(requires using a library like idb-keyval for easier use):
// services/auth.js (updated)
import { get, set } from 'idb-keyval';

const token = await get('auth_token');
await set('auth_token', token);
await remove('auth_token');
// services/auth.js (updated)
import { get, set } from 'idb-keyval';

const token = await get('auth_token');
await set('auth_token', token);
await remove('auth_token');
4. Data Store like Vuex/Pinia/...
// This is a VueX example
// store/auth.js
export default {
state: {
token: null,
currentUser: null,
},
mutations: {
setToken(state, token) {
state.token = token;
},
setUser(state, user) {
state.currentUser = user;
},
},
actions: {
login({ commit }, { username, password }) {
// ... login logic
commit('setToken', token); // Update token in store
commit('setUser', user); // Update user data in store
},
// ... other actions
},
};
// This is a VueX example
// store/auth.js
export default {
state: {
token: null,
currentUser: null,
},
mutations: {
setToken(state, token) {
state.token = token;
},
setUser(state, user) {
state.currentUser = user;
},
},
actions: {
login({ commit }, { username, password }) {
// ... login logic
commit('setToken', token); // Update token in store
commit('setUser', user); // Update user data in store
},
// ... other actions
},
};
Hope that helps a bit 😄
StilauGamer
StilauGamerOP6mo ago
Yeah, I will read through and think about it deeply... What I've currently done is: - You log in with discord. - You get redirected back to the website and it gets the OAuth code. - It grabs the access_token, refresh_token, etc from discord. - Stores it in a JWT - Saves the JWT to a cookie - Gets the cookie and verifyes the JWT when accessing pages, etc through middleware. This way I don't store any of the data on the server, and its all locally.. And then I would say store the discord id in a database for a more thorough perm checking... Is this a bad way of doing it? Only worry I am having is with cookie stealing, etc? If someone steals the JWT and tries using it? Then that would work right?
Nasr galal
Nasr galal6mo ago
hmm, using XSS attacks, yes, if an attacker tries to get it, he can go through. Your approach has advantages though: - Improved Security: Not storing access tokens or refresh tokens on the server reduces the attack surface and potential data breaches. - Scalability: This approach can be more scalable as it doesn't require server-side storage for user tokens. Talking about disadvantages: - Security Concerns: a. Cookie Theft: If an attacker steals the JWT cookie, they can potentially impersonate the user. b. XSS Attacks: Cross-site scripting vulnerabilities could allow attackers to steal the JWT from the client-side. c. Limited Functionality: Storing only the Discord ID in the database limits what information you can access about the user without making additional API calls to Discord. d. Revocation Challenges: Revoking stolen JWTs can be more difficult as they are stored on the client-side. --- For now, on the client-side, Here are some ways to mitigate the security risks: --- 1. HttpOnly Flag: Set the HttpOnly flag on the cookie to prevent JavaScript from accessing it directly, reducing the risk of XSS attacks. 2. Secure Flag (HTTPS): Ensure your website uses HTTPS to encrypt communication between the browser and server, protecting the cookie during transmission. 3. Shorter Expiration: Set a shorter expiration time for the JWT to limit the potential damage if it's stolen. 4. Refresh Token Management: Implement a mechanism to refresh the access token before it expires using the refresh token obtained from Discord. Store the refresh token securely on the server (not in a cookie). there are alternatives, but will need server side work though 🙂
StilauGamer
StilauGamerOP6mo ago
Okay.. So there are a few issues that might happen.. So how about this. On the server side I would store: - A unique ID for the user, discord id. - Refresh Token - Time of expiry - Access Token - Other data I want Inside another DB table. - Discord ID of user - A unique cookie - The IP that the cookie was authenticated on And on the client I would have a JWT that would have: - Discord ID - The cookie ( This is used to make sure that your cookie can be authenticated with. ) So what it does when you log in is that it cross checks the cookie and discord id to make sure its acceptable. This way its both encrypted in a JWT with a secret key, aswell as each cookie is IP whitelisted and I can setup a system of every cookie that has been authenticated on different ips. And then remember to active HttpOnly and HTTPS How would this be? This would somewhat protect u against cookie theft, aswell as XSS attacks, it would also have more functionality when it comes to storing the access token, etc on server lets me have more functionality at my hands. And revoking would also work as it would be done through the unique cookies? But then I would remove both the advantages getting from only having it client sided 🤔
Nasr galal
Nasr galal6mo ago
hmm, yeah, I think you may choose the best fit depending on the highest priorities. Both approaches have pros and cons. Sometimes it puts us on a trap trying to choose between both of them. I would say if your app is a Data-Driven one, we may think of Server-sided way. In the mean time, I came across Web Application Firewall (WAF) which sounds a nice addon for adding a protection layer. may be something like this: https://github.com/timokoessler/easy-waf and here is the thinking emojie of mine 🤔 😄
GitHub
GitHub - timokoessler/easy-waf: An easy-to-use Web Application Fire...
An easy-to-use Web Application Firewall (WAF) for Node.js. Can be used with Express, Fastify, NextJS, NuxtJS ... or plain Node.js http. - timokoessler/easy-waf
StilauGamer
StilauGamerOP6mo ago
So you think this would work pretty decently? Your smarter than me in this area, so just seeking some advice 😂 I personally find this most interesting if you encrypt all of it well on the server side
Nasr galal
Nasr galal6mo ago
I am not a Pentester 😄 however, I do prefer server-side. Despite its complexity, but it is handy when it comes to security stuff. 🙂 yeah encryption is a powerful way too. Let's keep this ticket open, we may learn something new out of it 🙂
StilauGamer
StilauGamerOP6mo ago
I find server sided a lot more secure and I feel more secure as a user when its not stored on my pc... Thats why I thought about my way of doing it. It gives the user more flexibility on what devices and what IPs might access their account.. Aswell as you can show a last active time on the cookie to show that some people might've been on it recently.. I find that this way is a little more secure and gives you both encryption on client side with storing it all in a JWT token and on the server side its all encrypted so I can't as a host go and look at it in plain text
Nasr galal
Nasr galal6mo ago
That's correct, on server, we can have a more granular control over the data. Since the browser is not the secure place to store the data in. As per OWASP security standards, It is highly recommended not to store any confidential or privacy data as it is exposed to be breached. https://owasp.org/www-project-mobile-top-10/2014-risks/m2-insecure-data-storage Sometimes, one little code mistake in the client code could lead to data leakage somehow. That's why I do strongly agree with your thoughts around making it on server side. However, some simple apps don't need server-side approach, that's why I am trying to be wise when choosing which matches which. As a world class level approach, for sure it should be a back-and-forth between client and server.
M2: Insecure Data Storage on the main website for The OWASP Foundation. OWASP is a nonprofit foundation that works to improve the security of software.
Want results from more Discord servers?
Add your server