Adding JWT support to the client. Storing the token in local storage, then creating a http interceptor to add the token to requests made to the server. Also implementing logout.
Kent C. Dodds: [00:01] OK, so here we have our application. We can login, and get users. We don't have to be logged in to get users, and that's what we want to try and protect. Also, we don't actually know if we're logged in from the UI, so we're just going to add this really quickly. We'll say H2, Welcome, and it'll be VMuser.username.
[00:26] I'm not going to hide this. Normally you'd want to hide this if there is no VM.user, because this really doesn't make sense, but I'm going to keep it here because we can still get users, and I want to show that until that resource is protected. Anyway, if we login here, now we can see, we do actually login, that comes from the server. Here we have our application.
[00:46] There are a couple of things that we want to do to this application. If you recall from previous videos, when we login, the server is sending us back a token, and we want to save that token, and send it on every request to a protected resource, and so that's what we're going to do in this video, is save this token in local storage, and then set up sending that token on every protected resource request, and then we'll also implement logout.
[01:14] Let's go ahead and set up saving this to local storage. We're going to create a factory that will manage our token for us. We'll just say app.factory, and it'll be an auth token factory, and this will be a simple factory, it'll have a get token, and a set token, which will take a token. We're going to inject window in here so that we can get our store, which will be local storage. Then we'll have a key, and that will be auth token, and then we'll have our get token, and set token.
[01:52] Then here, get token will just simply return store.getitemkey, and our set token will say if a token is provided then we'll say store.setitemkeytoken else store.removeitem. Now we have our auth token factory. When we login, we want to save this token, so we'll add a then here. Here we'll take auth token factory and set token to the response.data.token, and then we'll return the response for future items in the chain.
[02:31] We'll need to inject the auth token factory. Now let's go ahead and see this in action. If I refresh the page, get that new client code, we'll say kentcdodds P login, and let's look at our local storage here, and our resources. There we have our auth token. Now we're storing our token in our local storage, and we want to us it on request to protected resources, and so now we're going to use what in Angular is called an interceptor, and we're going to create that as a factory.
[03:04] We'll say app.factory, it will be our auth interceptor, and interceptors have a couple of cool things on them. You have the request, the request error response, and response error. Each one of them is doing different things to the HTTP config. The one that we care about is the request, so we'll have request and it will be add token, and then here we'll implement that. It'll take the config, and it'll return the config.
[03:35] Here we'll have a token, and let's inject our auth token factory, and will get the token. Now if there is a token, so if the user is authenticated, then we're going to add this to a header on this config object, so we'll say config.headers is equal to config.headers or an empty object, just to kind of protect ourselves there. Then we'll say authorization equals bearer plus the token, and this is just part of the spec. It's the authorization header, image prefixed with bearer space, and then the token.
[04:16] Now we're sending the token on every HTTP request, but not quite actually. We do need to do one more thing, and that is in our app config, we need to inject HTTP provider. On that HTTP provider, it has an array called interceptors. We're going to push on that array just a string that is the name of our interceptor. Angular will look up this interceptor, and every single request that HTTP makes will pass through our function that we defined down here, this add token function.
[04:51] We can see that in action here. Let's refresh our client code, we'll say kentcdodds P, and let's go ahead and look at our network tab. We login, and we can see the token is given to us. We can see in here in our resources we have that token there. Now if we say get user, we'll click here, look at our headers, and it's right there, our auth authorization header with the bearer and the token.
[05:21] Now we need to alter the server to take this token into account when get user is invoked so that that resource can be protected. That's what we'll do in the next video. One more thing that we want to do in here that I want to show you is how easy it is to logout. We have this auth token in here, we're logged in, and it's very simple to add a logout, so we'll just do that now.
[05:45] We'll create a button called logout, I'll just add a break here, and we'll say ngclick is equal to vm.logout, and then up here we'll say vm.logout is equal to logout, and we'll create logout here, and we'll say userfactory.logout. Then in our user factory we have it log in, we'll have it logout. Then well logout, and we say that auth token factory set token to nothing, and that will remove the token from local storage, because that's how we implemented it down here.
[06:29] Then for the view side of things, will say vm.user equals null. If we refresh the page, you can see the auth token is still there, and we don't have any logic to automatically log the user in to the client, and we'll build that in the future. But here we have the user logged in, now we have this logout button. If we click logout, you can see that the auth token is removed from local storage, and no longer is the user name appearing here.
[06:55] If we refresh, that key is still gone, and then we can login and logout. Just in review, we simply added a auth token factory to store the auth token in local storage, and then we get that token from local storage on every single request using our auth interceptor, and attaching it to the authorization header, with bearer and token. Then we take that auth interceptor and push it onto the interceptors of the HTTP provider.
[07:27] We also implemented a logout function that simply set the user to null, and removed the token from local storage. In the next video, we'll talk about what we need to do to make it so that when a request is made to get a random user, the server will take that token into account, and protect that resource to only those who have a signed, verified token. That's what we'll see in the next video.
[07:52] [cuts off]