Current section: Cross-Site Request Forgery 4 exercises

Security with Authenticity Token and CSRF Validation


00:00 Let's go ahead and start in the note ID route where we have that delete button. So the what we really are our objective here is to add the authenticity token input. And if I just add that and then we pull up our delete button in here, then we'll see we've got our form, but it's not rendering anything.

00:20 The reason it's not rendering anything is because we haven't actually provided that token here. We have loaded it in the root, but we need to provide it. So let's go to the root and we'll come down to our app with providers that we've got and wrap everything in the authenticity token provider. So right here

00:39 authenticity token provider and stick everything else in there and then we can say our token is equal to data dot CSRF token that we provided from our root loader. And now with that we've got our token right here.

00:58 So if we we can't really compare this to the cookie ourselves because the cookie again is signed and so it's going to look all funny, but we can go in here and finish up the process of verifying that it's correct and it should be correct and we can test what happens if it's not correct as well.

01:16 So let's validate our token and we're going to use CSRF. We're going to need to import that from our utils and then we've got validate and to that validate function we can actually we have two options here. We can either pass the request or we can pass the form data and the headers.

01:35 Because we're actually parsing the request ourselves, we need to be we need to pass the form data because otherwise you'd have to clone the request. You can't parse the request form data twice. And so if we pass the request right here then CSRF util would try to parse the form data and it would blow up because we already tried to use that.

01:55 So we're going to pass the form data that we already parsed and also the request headers so that they can get the cookie for their check. And this is going to be async. So we're going to await that and that should be enough actually to prevent malicious actors from doing what they want to do. So let's get our

02:18 application up and going again. Looks like it fell over for some reason. So here we go. And then we can come here. We've got that hidden field right there. If I click on delete, then we take a look at our network for that post request and here we've got our CSRF token as well as our intent.

02:36 So things are working as they should from the beginning from the get-go, but then if I come over here and I try to delete this, so now I'm a malicious actor. I don't have the CSRF token in my form. I hit delete and it goes kablooey because it can't find the CSRF token in the body, which is not entirely

02:57 useful to me as a user, but if I'm a malicious actor, I probably don't... I personally don't care about malicious actors having a positive user experience anyway. But the other problem here though is that we're getting a 500 internal error. Not really something that is accurate or correct. So really having a 403 response is more correct.

03:18 And so that's what we're going to be changing things to in a similar way to what we did with our our honeypot token. So we're going to add wrap all this in a try-catch and then we're going to say if the error is an instance instance of that's a CSRF error

03:38 that's coming from Remix Utils, then we're going to throw a new response and we can just say invalid CSRF token. Yep, that works with a status of 403. That's the correct status here. Otherwise, we'll throw the error because maybe something else went wrong and that really would be a 500 error for that.

03:57 So now if we come over here and say hey, I want to be a bad actor and then we can delete that and kablooey. The other thing about this is even if we do provide it, if it's not correct then it's also going to blow up on us as well. So let's review really quick. In the root, we added the

04:19 Authenticity Token Provider so that we could provide this token. So all instances of our Authenticity Token input could have access to that token value. And so they render the token value, the form automatically just will serialize that for us and then in our action we can do this

04:41 try-catch around the CSRF validate. We pass the form data, we pass the request headers and then we check if this is a CSRF error, then we know that was a 403, that CSRF token was invalid. And now we're not vulnerable to CSRF attacks, which is super awesome.

05:00 Feel free to take this a little further and maybe move this into the CSRF util so that you don't have to do all this try-catch nonsense like we did with the honeypot. But that's it. Now you can add the honeypot and the CSRF thing all over the place and you can feel pretty protected in your forms. So well done.