Check out a free preview of the full Web Security, v2 course
The "CSRF Token Exercise" Lesson is part of the full, Web Security, v2 course featured in this preview video. Here's what you'd learn in this lesson:
Steve instructs students to implement session management and CSRF protection in the provided social media application. He walks through the abstractions he created for creating and getting sessions, and how they set the cookie accordingly. He also shows how they handle the current user middleware and protect post requests with CSRF tokens.
Transcript from the "CSRF Token Exercise" Lesson
[00:00:00]
>> Steve Kinney: There's another one here called socialite, which is a social media app. It's great, you should totally use it. And it has the ability to post stuff as well. And so your job is to npm start. And this one's a little bit more fun, because unlike the rest of them that had a hard coded set of users, you can go ahead and sign up too, right?
[00:00:30]
You can make an account, and if it's running on localhost, you can talk to yourself all day. You can make two accounts and talk to yourself, too, that seems legit. And let's see if we can kind of create a version of the same attack. You could even take that meme page I had at evil and just point it at a different localhost and be good, right?
[00:00:49]
You can set up your own page. You can do whatever makes you happiest, right, but let's try it out. And it'll be the same technique to fix it, but I think there's enough step in this one that it's worth getting your hands dirty to generate a token with the session, put it in here if you can watch me sign up later.
[00:01:07]
You'll see a tweet form. It looks like what you think it looks like. And we can hopefully protect that post request from CSRF or CSRF.
>> Steve Kinney: So I made one booboo in the very beginning, which is when the booboos get you, right? A joke that when you're writing code at home or at work, you make a booboo in the very beginning, you just fix it later.
[00:01:30]
When you're teaching a live coding, [LAUGH] then you have to go and act like you have to go kind of start from where that where we had that detour. Let me show you the booboo that I made. The very beginning when I made that table, I called the ID column sessionid instead of ID, right, so, sessions.sessionid.
[00:01:55]
So session.id, and so in the very beginning, in that middleware that we had, I'll show you in getSession, even before that, in getSession.
>> Steve Kinney: One of those first helper functions that I made, which I guess I can make the point that having one helper function in one place means that if I was using this all over my code base, it would not be the greatest terrors I've ever caused my codebase was find and replace gone out of control.
[00:02:26]
Was originally when I first wrote the code, this was ID, I meant this to be sessionid. So one of the things that we have in the database now is this sessionid, userid, and token. I wish I made this id, so it was sessions.id, but I'm not changing the code now.
[00:02:46]
And this is how tech debt accrues, everyone, right? It works, and I'm not changing the code and you come to regret that six to nine months later. Cool, cool, cool. You know that thing when you're doing a PR, whether you're the one opening it, or you're the one commenting, where the two of you have just given up and we're just gonna merge it because nobody wants the morale on the team to go any further down.
[00:03:10]
So we have that table in there. I did make two abstractions, which did help me. This create Session, really, all it does is we make two different tokens. We make this sessionid the idea could have also been that random hex that we made before, and we make this tokenid.
[00:03:26]
Why did we make two different IDs? Because one goes in the cookie and one is gonna be hidden in the form, right? Because if they somehow got the ability to send the cookie, we don't want them to also have the token right next to it. Cuz if you put two keys to launch missile and you put the two keys on the same key chain, you haven't really done anything.
[00:03:46]
So we've got those separate and we do store them in the database with my regretful sessionid instead of ID. But we're here, we deal with it. I think it's cuz I had it called up here, whatever, it doesn't matter. And then we've got this getSession where, again, I had that mistake earlier that we've since fixed, which is where we sessionid matches the sessionid.
[00:04:03]
We'll go ahead and get a session. So I've got some abstractions for getting and setting sessions. This one is more important, cuz I do it on both sign up and log in, right? And so now, we go ahead and we do, in fact, when we post to both of those, we go ahead, we make the user.
[00:04:18]
There's no user, then we're like, hey, there's nobody in there with that username and password. If there is one, then we go ahead, we create that session in the database and then we set the cookie accordingly. We do basically the same thing on the account creation. Then in that current user middleware, we have to do a little bit more of a dance than we had previously, ehere we start out with that sessionid, right?
[00:04:43]
We go and get the session. We can console, log it for sanity. If there's no session, keep it moving. Don't even go looking for a user, cuz you're not gonna find anything in the database. At that point, there will be no local for the user set and no local for the session set.
[00:04:58]
But if we did have a session in place, okay, then ideally we should have a user. Now, could you write bad code and if someone deletes their account, not delete their session and get weird with it? No, cuz I don't think they could log in. So a little more error handling might be helpful here.
[00:05:14]
But then we basically set it, so now we've got access to the token. We've got access to the userid. And that kinda creates the same, little bit more complicated, but roughly the same flow. I mean, the last part was just in posts, we do the same move with the hidden field.
[00:05:31]
And then when they go to post one, which is the very fun endpoint called app.post/ or app.post/posts.
>> Steve Kinney: Right, we do the same check that we did in the last one where we got to do that part. We can grab the content and the CSRF token and basically, yeah, if that's not the one attached to their session, we want res.locals.
[00:06:10]
>> Steve Kinney: Then tell them they're not authorized, right? And so we've got those same protections on our post requests now that we had earlier with a little bit more dance of what we saw with creating sessions at the very beginning. So ideally, what I ate for lunch today, I had burrito bowl.
[00:06:30]
>> Steve Kinney: No, now what? It should be easy. Local session token, yeah, that's not what it's called.
>> Steve Kinney: What did I call it? My last one, so close, so close. I called it just res.locals.token. Okay, cool, cool, cool.
>> Steve Kinney: We know the system works. Cool, and so now we've got it in there as well, right, and so we kind of complete the circle.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops