Auth0 badgeAuth0 University

Angular JS Authentication: Securing your app with Auth0

Angular JS Authentication: Securing your app with Auth0

  1. Course Catalog
  2. Angular JS Authentication: Securing your app with Auth0
  3. Preserving Authentication on the Frontend

Preserving Authentication on the Frontend

All right, so we're in a pretty good spot here with our application. We've got authentication happening with Auth0, so we can login and we can get a JSON Web Token for our user and get their profile saved here in local storage. But the problem is if we go to refresh, what we see is that our state goes away. So you'll see here that the profile and the logout button go away because that is authenticated Boolean that is sitting on the auth service gets flipped to its default, which is false.

Now, ideally, in an AngularJS app, there wouldn't really be a whole lot of page refreshing happening, but it might be necessary from time to time. And if the user goes away from the app, if they close their tab and then come back to it, and if they still do have a valid JWT in local storage, they're going to be prompted to login once again. And so obviously, this isn't really a very good user experience.

So why don't we take some time to fix that up? And what we can do is we can put in some code that watches for any changes to the location we're at in our application. So right now, we're at the home route, for example. And we can also go to the profile route. It's going to watch for any changes to that location and when that location changes, we'll have the app check for whether or not the user still has a valid JWT in local storage.

And if they do, we'll just make sure that the Angular app knows that they are authenticated. So let's head over here to our app.js file. And to make this happen, we'll need to tap into the run block for our application. So we've got our config block happening here, and it's setting up our auth provider and then also all of our routing and everything. And here in the run block, we can define some logic that we want to have happen after the application is running.

So run takes a function, and it's here that we can inject any dependencies that we'll need to make this block of code work. So we're going to need route scope. That is going to be the spot at which we look for changes to our app's location. And then we'll also want our auth service and we'll need store. Then we'll need JWT helper. And that's a service coming from Angular JWT that gives us some tools for inspecting JSON Web Tokens.

And then finally, let's get location. So again, that will allow us to navigate to a different spot in our application. So then within the body here, what we'll do is we'll watch for changes to the location. And the way that we can do that is we can use the route scope on method. So we'll do route scope $ on. And that's going to accept the name of an event to watch for. So we want to watch for location change start.

So this event, this location change start event, gets fired any time that we move to a new spot within our application, any time the routing changes. And this event's also going to happen any time the page gets refreshed so we can use it to check for the user's authentication state. So then the second parameter is our callback. And so we'll just define some logic within this block here that says let's look for a token. So we'll do var token equals store get ID token.

And then we'll say if there is a token, if that was successful in grabbing a token, then we want to check for whether or not it is expired. So we'll do another if block here and we'll say if that token is not expired, and we can do that by doing JWT helper. Is token expired? And we'll pass in our token. If that's the case, and also if the user is not authenticated, and we can check that with our auth service, auth is authenticated, what we want to do is authenticate the user.

So what we can do for that is use our auth service and call authenticate. And we can pass in our profile, so we can do store get profile. And then the second argument is going to be the token, so we can just pass in our token like that. So there's a fair bit going on here, so let's step through it one line at a time. So we're looking for a token called ID token in our local storage. And if that is present, we want to check whether or not it is expired.

So we can use the JWT helper is token expired method, passing in our token. If the JWT is not expired, and if the user is not authenticated, then we want to go ahead and authenticate the user. The reason being, that if a token isn't expired, well, the user is effectively authenticated as far as the application is concerned. So that's all going to take place if there's a token, but if there's not, let's define some other behavior.

The other behavior simply being that we want to redirect the user to the home route so that they can login again. So for that, we'll do location and we'll go to the path of home. Okay, so why don't we save that? And let's go over and see if this is going to work. So, the first thing I'll do is just delete our items here from local storage. And we'll go through the step of logging in again. Let's go back to the home route here and let's do login.

And then we'll login with our user. So we've got our items in local storage. Now, let's go to the profile and let's try refreshing. And so when we refresh, now you see that we've still got our profile and our logout button up here. So our state is being preserved. We've gone through the process of checking for our user's JWT in local storage. And if it's there and it's valid, well we just use it to authenticate the user on the front end again.

Notice here that we're not doing any kind of request to Auth0 to check for a new JSON Web Token or anything. We're just dealing with the front end. And if we check our get message buttons here, we can do a regular public message. And that still works. And then if we do a secret message, we see that still works. But now, here's a scenario that we should think about. What happens if we're here in our application and it's working just fine, and then all of a sudden our token expires?

Well, we aren't redirected or anything. We're rather still here at our profile area. What happens if we go to, say, get a secret message? Well, that request will go through and it will, of course, attach this JSON Web Token in local storage. But on the backend it's going to be rejected because it will be expired. And what will happen is we'll get some kind of 400 series error back. Now, what's the best way to handle this on the Angular side?

Well, we can either show a message to the user saying that their token is expired, but that's not really all that intuitive, I don't think, for most users. I think probably the better option would be to redirect the user to wherever they can login again. And in our application, that's going to be the home route. So we want to redirect the user to the home route, and then have them login again from here. And we can do that by wiring up an HTTP interceptor. We'll do that in the next lecture.