Current section: Logout 6 exercises

Logout Functionality with Session Storage and CSRF Protection

Loading solution


00:00 So, the first thing we want to go to is our username route, and in here, we've got our form for that logout. So, that logout button right there. We're going to want to post, so method post, because cross-site request forgery, all that good stuff. Speaking of that, let's add

00:18 our authenticity token input from RemixUtils, and then we're going to post to the action slash logout. Now, if we don't have the action, it's going to post to this route, and so we could put the action inside of the $username, but we're going to have a couple of other places where we want to log the user out. So, being able to have

00:37 just a specific route that's responsible for that will make it easier for those as well. So, with that now, we can go to the logout route, and we're just going to have a loader in here that redirects the user to the homepage in case they end up on the logout route for some reason, and then we'll have an action, and this action needs to get

00:56 the request from DataFunctionArgs, and here we're going to get our cookie session from await session storage.getSession from the cookie header, and then all we have to do is delete this session, and in fact, we don't even need to get

01:16 the current existing session from the cookie header because we're going to delete it anyway. So, we just need to get the session object so that when we destroy the session, it will be properly destroyed. So, let's say headers and setCookie,

01:32 and this will be sessionStorage.destroySession, and that is it. We get our cookie session right there. Boom. So, in fact, we don't even need to get the request right there. Fancy that. So, let's just try this out and make sure that this is going to work for us.

01:50 We'll hit logout, and I'm successfully logged out. The reason that actually ends up working is because in our root TSX right here, when it re-evaluates after our mutation, it's going to call this loader again, and it's going to say, hey, get me this session storage and that cookie session or that cookie doesn't exist anymore,

02:10 and so it's a brand new session object. So, of course, it's not going to have a user ID in it. This might also help to take a look at the headers as well. So, let's pull up our DevTools and look at the cookies here. Let's clear them all out,

02:26 and we get our CSRF cookie there by default. We'll log in and say, Cody. Cody loves you. So, now we have our session right there, and if we come in here, let's go to our network tab, have that all cleared out, and if I click on logout,

02:44 then we're going to get this post request right here. That post request is going to send a response that includes a set cookie. EN session is an empty string. The path is everything. So, like all of our default configuration that we had before. But the interesting thing here is that

03:00 the expires is going to be set to way in the past, and so the cookie is going to clear out the value. So, not only are we setting the value to nothing, but we're also telling the cookie to be expired immediately just in the past. So, let's get that cookie out of there. So, now if we look at our application cookies,

03:19 that cookie is no longer even in our application. So, that's really nice to have it destroyed like that, because now we're not going to be making requests that include those cookies all the time, which is sweet. So, in quick review, we updated our username to have a method of post and an action of logout and include our authenticity token input

03:39 to protect from CSRF attacks, and then our action just grabs a session storage object and sends back a set cookie header to destroy that session cookie, and that is how you do logout.