Check out a free preview of the full API Design in Node.js, v4 course
The "Validating a Bearer Token" Lesson is part of the full, API Design in Node.js, v4 course featured in this preview video. Here's what you'd learn in this lesson:
Scott adds code to validate the JWT token. The validation logic ensures the token is well-formed. If not, an error is thrown, and the server again issues a 401 unauthorized request. A question about API rate limiting is also addressed in this lesson.
Transcript from the "Validating a Bearer Token" Lesson
[00:00:00]
>> Okay, so now I'm gonna trick it. Now I am gonna send something out. I was typing some characters. Now what? Well, this is gonna hang now cuz I'm not calling next or anything, so it's just gonna sit here. But it didn't break. So our protect middleware isn't good enough yet.
[00:00:13]
I bypassed it by just typing in some random strings. So we're not there yet. We check to see if it was there, that's great. And now we gotta check to see if it's real. And that will stop this from happening. So let's go do that. So now what we'll do, is we're gonna check to see if this is actually real or not.
[00:00:29]
So the way we'll do that is we'll grab the token off the bearer and check to see if there's an actual token. And then I'll give you another check. So let's do just that. Let me go to off. Next check would be, let's just say const. I'm gonna destructure here, so I'll put an empty array for now, and I'm gonna say bearer.split on an empty space.
[00:00:57]
The reason I'm splitting on empty space because I'm saying you need to send me a token that looks like this. Let's just bearer, space and then your token here. So I'm splitting on this empty space, and split returns an array. And it should have the word bearer in the first argument and the first index of the array, and then the token in the second index of the array.
[00:01:18]
That's what split's doing. So that's what I'm saying is the API creator, that's what I want you to send me. So that means the first thing here is the word bearer. I don't care about it, so I'm gonna put a comma. But the second thing is a token, I care about that, so I'm gonna say token.
[00:01:35]
So now we have a token. Then I can say, if not token, you already know what's about to happen. I'm about to give you the same thing I gave buddy up here. It's a 401 unauthorized. Or I can say not valid token. Whatever I wanna put. Okay, so to test this, now let's restart our server, go back to turn client.
[00:02:08]
This was able to fool it last time. Let's see if it fools it this time. I think it still fooled it, so we're not there yet. We still haven't built a sophisticated enough protect to stop something as trivial as just typing in something here and hitting Send. So not quite there yet, it's still hanging.
[00:02:32]
I'm guessing the split actually created, well, yeah, if you split on empty space with nothing in it, it's still gonna just give you back the string. So it's still gonna bypass it. The split is not good enough yet. So now what we wanna do is we wanna like okay, cool, you got past here, you sent up a token, you actually formatted it correctly somehow, but is it a real JWT signed by this secret?
[00:02:58]
That's the last check. So if you can get past that, then you must be real, or you steal someone's JWT, which means you're real. So let's do that. Let's go back to our code, And we'll say, okay, cool, we're gonna try to cache this because it could break.
[00:03:18]
And if it breaks we don't want the server to break because this method from JWT will break if it doesn't verify. But we don't want someone sending a wrong JSON web token breaking our server because the user messed up. We don't want the rest of our users suffering because someone tried to authenticate incorrectly.
[00:03:39]
Imagine someone's server crashing because you forgot your password. That's the equivalent of this. I don't want that to happen. Someone forgot their password, and that crashed a whole server for everybody. That would be terrible, so that's what we're trying catching this. Okay, so now let's say const user = jwt.verify.
[00:04:04]
So we wanna verify this token with this secret, so process.env.JWT_SECRET. So we're gonna get this token, and then if not user, right? Or there we go, I'm just gonna assume that it is. So we got that, otherwise, this would actually break. So now, we'll just say req.user. I've augmented the request object, = user.
[00:04:31]
Which should be the object that we signed all the way up here. So should be an object with the ID and a username cuz that's what we signed in to existence. And then I can say next, I'm done, not next tick, but next. And I guess I need to put next here cuz it is a middleware.
[00:04:56]
If any of that breaks, you know what we're doing, we're coming over here. We're saying no. And I'm just gonna log the error just so we can see it. So we're gonna try to verify this token with this secret that we signed a token with. If it is a user, we'll attach it to the request object we'll call the Next.
[00:05:19]
So anything in the stack can now req.user, and see the user who's currently making the request. They can identify them. It will have an ID and a username on it perfect for query to database. Otherwise, you know what's gonna happen. You're getting a 401. So let's give it a go.
[00:05:37]
So I think these are still gonna hang, means I still don't have any handlers. But we do have a handler in, where is it? There we go, gets slash first. I gotta make sure I go there. Okay so, let's try this. Stop, start it again. And now if I try to do this and I run this code, boom.
[00:06:06]
Now spoofing, JWT that got past those two steps are no longer going to get past that last step because it's not a valid token. Not a valid token, right? And we can go look at the error that the JWT logged, you can see right here. A JSON Web Token error.
[00:06:20]
JWT malformed. This didn't break the server though because I caught it. If I didn't catch this, if I did not wrap this in a try catch, our server would be off right now. It's still on. It's still on right now. But if I didn't do the try catch, it will be off.
[00:06:33]
And everybody would be tweeting us cuz our server died. In the middle of a ranked game or something like that. Something weird. So any questions on that? That was a lot. Authentication is tough. And it gets tougher than this, [LAUGH]. But for the most part, it's mostly just this.
[00:06:59]
Plus other stuff. Yes.
>> Would API rate limiting be also implemented in a middleware?
>> Good question. So API rate limiting is a mechanism you would use for an external facing API. So as in your product is an API. Again, I hate to use stripe again but stripes product is an API, their product is documentation.
[00:07:21]
So they would have something like rate limiting because they don't want one person killing all this. Somebody could just write a script on an infinite loop and deploy it to 30,000 IP addresses and just try to bring down your server. They don't want that to happen. So they implement something called rate limiting, which looks at an IP address and limits how many times an IP address can make a request per second before it gets blocked for X amount of time before they're allowed to do it again.
[00:07:52]
Yes, you could do that in the middleware, but for more performance, you don't want that request even reaching your server. Because yes, you stopped it from reaching the handlers, which talked to the database, which are the biggest performance hit, but it's still on your server and taking up resources there.
[00:08:12]
So typically a rate limiting for a more sophisticated API would probably be added before the API. So technically it is kinda like middleware, but middleware on the network layer and not on the code layer. And this would be like a proxy or an API gateway or something like that.
[00:08:29]
Which is another server that sits in front of your server. And that server does things like rate limiting and access control. So that way your server can safely make the assumption that this request is safe and ready to go. And that's just a whole another thing. There's literally products that are just that.
[00:08:46]
Okay, everybody's an expert now?
>> No.
>> [LAUGH] All it's tough. Okay, well, at least we're protecting our routes now. You can't access any of these routes. They're good the guards, its cool.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops