
Lesson Description
The "Storing JWTs on the Client" Lesson is part of the full, Build a Fullstack App with Vanilla JS and Go course featured in this preview video. Here's what you'd learn in this lesson:
Maximiliano explains the importance of storing authentication keys client-side using local storage or IndexedDB for actions requiring authentication. He demonstrates creating a service to store data, like JWT tokens, and using a proxy pattern in JavaScript to manage events like saving token changes to local storage.
Transcript from the "Storing JWTs on the Client" Lesson
[00:00:00]
>> Maximiliano Firtman: So, now with that, that is actually the key. So, we need to store the key in our pocket. In this case, the browser's pocket is actually local storage, index DB, any place where you can access that later. Okay, does it make sense? So then, so we need to store that client side, and then send that.
[00:00:28]
We will see how to send that later on other requests that are actually targeting, let's say actions that needs authentication. Not on every action because we can get movies and that's free. You don't need a key to get your movies, but you need the key to save a movie in a watch list.
[00:00:52]
You need a key to get into some section that is actually special, okay?. So to do that, just store the key first. We will go back to the client now, so to the Public folder. And within services, we are going to create a new service. We will call that store, where we are going to store data, okay?
[00:01:17]
And the store will be just, for now, just the wt, the token, that is gonna be null by default, okay?
>> Maximiliano Firtman: I'm missing an equals. And also, I'm not sure if you are used to properties with getters. So I can just say, get loggedIn is equals to if jwt is not null.
[00:01:51]
So that means, you need a comma here. If at any time you wanna know if the user is logged in, clients style, or you think the user is logged in, because maybe the token is expired, okay, but we don't know that. To actually know if the token is expired, we need to make a request to the server.
[00:02:09]
The server is the only one that can open the package and see if it's expired. Okay, so if we have a token we think that we are logged in. Make sense? So we just call store.loggedIn and it will give you true or false based on the jwt. But in the future we change how we define if the user is logged in or not, we change that.
[00:02:31]
And also something that we can do, is that we are going to create a proxy. Do you know what a proxy is in JavaScript?
>> Maximiliano Firtman: Have you ever seen this before, new Proxy? A proxy is a design pattern, but also it's an implementation that we do have in JavaScript, that will let us wrap, like decorate an object with another object that is gonna be our public interface.
[00:03:08]
Now that proxy has, for example, events. So every time you're trying to change the store, I can do something here, so we can hook events over the store. For example, one event is set, we receive the target, so the object that we are changing, the property that we are changing and the new value, okay?
[00:03:33]
So I will actually do something like this, if the user I can use it for switch. Most of the time it's a switch. Each in case you have different properties, okay, but we have only one jwt, so let's do an if. If the property that someone is changing, you will understand this in a second, is jwt, so it's the one that I care about.
[00:03:55]
I will first say, I wanna change the current property, so let's change it. But also I'm going to store that one in local storage. Do you all know what local storage is? It's a client side storage, key value, key strings, value strings, both are strings. It's limited in size, it's five megabytes, typically in every browser per origin, so per domain.
[00:04:26]
And it's five megabytes, but most WebKit based browsers, including Chromium-based browsers, because it's coming from WebKit Chromium. They're using UTF 16 to store strings, which means that they're five megabytes. It's actually half of that because this is two bytes per character, okay? So it's two megabytes, I mean for the JSON Web Tokens, good enough.
[00:04:49]
But if you have other stuff, be careful because you may wanna go and use IndexedDB for that. And if you wanna get more details into all those topics, I have another course in Frontend Masters on data storage, where we cover all these topics, okay? Local storage, IndexedDB, and so on.
[00:05:09]
So in this case, that means that every time I'm changing jwt, for example, if I'm saying store.jwt = new, I'm also saving that in local storage, that's what I'm doing. I'm changing the value here, but I'm also saving it in local storage. Okay, so it's like an event listener for changing the jwt value from my store.
[00:05:34]
Does it make sense? And finally, I need to return true, this is mandatory on every setter. That means that you manage the change, you change the value. And then I need to export that proxiedStore, default or not? Actually, if I'm doing this here, it should be equal default.
[00:05:57]
That means that from the outside, people will see the proxiedStore, not the natural store, okay? So if they change the jwt, we know for sure that we will save it a copy of that in local storage. Does it make sense? So because we are saving a copy in local storage, that means that here somewhere when the page loads or when this module loads, I can check if I do have a value in local storage.
[00:06:32]
And if I do have a value, I will do the reverse operation. And I have a request for you. Do I have an infinite loop here, or something like that? Because the same file is setting in jwt, and then we think that when we are changing jwt, we are going back to the local storage.
[00:06:53]
So it's not actually infinite loop, it's like we are setting the value and we are saving the value in local storage, but we are setting the value from local storage, so say it's like a triangle. Actually, the answer is no, because here I'm actually accessing directly this one.
[00:07:11]
I'm not going through the proxiedStore. From the outside of this module, they will use the proxiedStore. But internally I can save directly a value without the proxy being aware of that, okay? Does it make sense? Kind of, yeah. So
>> Maximiliano Firtman: Now in app js, after a successful login and registration, so here, when we are going to the account, I need to talk with my store.
[00:07:44]
By the way, how can I access the store? Well, my app should have the router and also a reference to the store that is actually in a separate module. Does that make sense? And then that store is getting the proxiedStore automatically because I'm in the outside. So now if I'm registering, I should get app.store now.
[00:08:14]
And app.store, we have, for example, the jwt property. I'm setting that, I'm reading that from the response. Okay, makes sense, and the same happens after logging. So if this works, let's see. Let me check if app js is importing the supporting the router, I'm not seeing the import for the store, which actually, this is the one, I can call it a store here, right?
[00:08:52]
>> Maximiliano Firtman: Now, we are talking. So I'm importing the store, even if it's called proxiedStore, the other side, I don't care, I call it a store here. So now it should work. So let's try, let's use Canary. So, let's go back to the login screen. So if I try to log in, one, two, three, four, five, seven login, I mean.
[00:09:21]
So I don't know if I save first, I can check my store from here.
>> Maximiliano Firtman: It's there, so I have it client side now, and I can check also on application. I have a section for local storage, and I can see here as well. That means that if I refresh, if I come back in a month, jwt will be there.
[00:09:48]
Unless I clear my browser cache or whatever, that jwt will be there. So now I have the token saved client side after registration and after logging.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops