All right, guys.
So up to this point, we can make a request to our login or our auth route.
And when that happens, if our email and password is validated, then it's going to go ahead and create
a Json web token and it's going to set it as an Http only cookie and then that can get sent with every
request after that.
Now we need a way to take that cookie and use it and we need to get the user ID from it.
All right.
So what we're going to do first is install another package called cookie parser that will allow us to
easily parse the cookie from the request object.
So I'm going to stop the server and make sure you're in the root directory, not the front end.
And let's install cookie dash parser.
Okay.
Once we do that, we can start up the server again.
Now to enable this middleware, we do have to go into the server.js and from here we want to import
cookie parser.
Let's do it right here.
We'll say import.
Cookie parser from cookie dash parser and then we just need to pass it into app dot use.
So we'll put that.
Right here, let's say cookie parser middleware and it's just app.use and then pass in the cookie parser
function.
Okay.
So now that should be all set.
What that will do is allow us to access request dot cookies and since our cookie is called JWT, we'll
be able to access request dot cookies, dot JWT.
Now where we want to do this is in middleware.
So in the middleware folder let's create an auth middleware dot JS file.
And in here we're going to import JWT because we need to verify the token.
So we're going to import that from Json web token.
We're also oops, we're also going to import that should be lowercase.
And we don't need.
Curly braces around it either.
So we also want our async handler, which isn't coming from Express.
Async handler.
It's our custom one that we created, which is going to be at dot slash async.
Handler JS.
Okay.
And then we also want the user model.
So we're going to bring that in from our models folder and then user model.
So we'll have two functions in this.
In this file we're going to have protect, which is going to allow us to protect routes for users that
are registered.
And then we'll also have an admin middleware function for users that are admins.
So like for instance, to get all orders you have to be an admin for that.
So let's start with the protect.
So we'll just say protect routes and I'm going to use copilot for some of this.
So as you can see, we're using our async handler.
We're wrapping the function here and in middleware, with any middleware function, we have access to
the request and response object and we can do what we want with those.
And you just need to make sure that at the end of your middleware function you call next because that
will just say, okay, we're done here, move on to the next middleware.
So let's go ahead and just initialize a variable called token.
And we're going to read, let's say read the.
JWT from the cookie and we can do that by let's take the token variable we just created and we can access
request dot cookies, dot JWT.
Okay, not token JWT.
And the reason for that is because if we go back to our controller, we go to our auth route.
See right here.
So this is where I set the token and I called it JWT.
If I called it token here, then I would be accessing request cookies dot token.
Okay.
But I'm putting whatever that is that JWT into a variable called token now.
So then we just want to check for that.
Let's say if.
Token.
So if token, then whoops, what did I do here?
So if token, then we're going to do something else.
So if there's no token, then we're going to say res dot status 401 and we're going to throw an error.
Okay.
And we're able to do this because of our error handler.
Now, if there is a token, what we'll do is have a try.
Catch.
And in the try, we're going to decode the token to get the user ID because remember when we created
the token, we passed in the user ID as the payload.
So we want to extract that from it.
So let's say const decoded.
And the way we decode it is with JWT dot verify and verify takes in the token and then also takes in
the secret which we have in our dot env file.
Now we want to get the user from the database that matches that that user ID.
So this is now an object that has a user ID field.
So we can say decoded dot user ID.
So let's go ahead and just await on and then we'll use the user model.
And we want to find by ID the decoded user ID.
Now, I don't want the password because this will return all the fields.
I don't want the password.
Even though it's hashed, there's no reason to get that.
So we can actually add on to that dot select and then just pass in minus password.
Okay.
Now what I want to do with that is then add that user to the request object.
So let's say request dot user equals that user.
And then this, this user object will be on the request object in all of our routes.
So for instance, if we're looking in or if we're working in the profile route, we'll be able to take
get the user from this request object and do what we want with it and it will be the user that's logged
in.
So hopefully that makes sense.
And then we just want to call next to move on to the next piece of middleware.
Now, if there's an error here, then let's go ahead and just set the status to 401.
And then for a message, we'll just say not authorized.
Instead of no token, though, we'll say token failed because if this is firing off, then it means
we have the token.
It's there, right?
Because we're saying if token.
But it's not, it's not the right token, it's not authorized.
And then let's just do a console.
We'll do a console log here of error as well, just so we know what's going on, if that does happen.
So that's our protect middleware.
Now.
I, we might as well just create the admin middleware while we're in this file because it's pretty easy.
So let's say.
Um.
I'll just say admin middleware and we want to I'm not going to export it from here.
We'll export it at the bottom.
But let's say const admin.
And any middleware function is going to take in request response.
And next.
And all we want to do is check the users is admin field and see if that's true.
So let's say if.
So we'll say if the request dot user because we'll have access to that and the request dot user dot
is admin.
So it was just saying if this is true, if if it is an admin, then we're going to just move on to the
next middleware.
Else.
Then we're going to send a an error.
So 401.
And we'll say not not authorized.
As admin.
And that's it.
Very simple.
And then when we want to use these middlewares, we can just pass it into the route in the route file.
I'll show you how we can do that in a minute.
So now let's just export.
Both Protect.
Protect and admin.
Did I export that up here?
I did.
So you can do it this way if you want.
Just have export.
But I like to do it at the bottom in this case.
Okay.
And now we can just bring these in to our roots or wherever we want to use them so we can close this
middleware file up and let's go into our user routes.
So right here and we need to figure out which of these routes.
Should be protected just for registered users and which ones for admin.
So first off, let's import protect and admin from dot dot slash middleware and auth middleware.
And then as far as the routes I want to protect, let's see, we have our profile, right?
So obviously to get the user profile or to update, we need to be registered.
So we want to protect those.
So what we can do is before the function name, we're just going to put in the protect middleware.
So that's to get user profile.
And then here when we have a dot put and update user profile, also going to add in protect there as
well.
All right.
So we can actually save that and we can try that out.
So if I go to my route to get a user profile and I click send.
Let's see.
So that's working.
And the reason for that is because the cookie is is here, right?
Because I had already logged in.
So basically what I can do is if I click right here on cookies and then I get rid of that.
And then let's go back to the body and let's send.
Now you can see not authorized.
No token because I implemented that protect middleware.
If I authenticate again and I have that cookie and I'm sending that, then then it will let me through.
So and it should be the same for the update user profile if I try that, I also get the message, but
I can still go to other routes like, you know, register or whatever that these still work because
I didn't add the protect middleware.
Now, as far as let's see as far as the get all users.
That needs to be protected, but it's also only for admins.
So what I'm going to do is add in front of it, let's say protect, but we're also going to add in the
admin middleware.
So now you can't just be logged in, but you also have to be an admin and we're going to do the same
thing.
We're just going to copy these two down here for delete for get user by ID and for update user.
These are all admin.
So let's go into this delete and add our protect admin.
We'll go into here where we have get user by ID and add, protect and admin and also with update user.
All right.
And the rest looks okay.
Now, this route here, I have slash login.
So to auth the user, we're going to slash login.
I'm actually going to change that.
I'm going to change that to slash auth instead of login.
It's just preference.
If you want to keep it as login, that's fine, but I'm going to change that to auth.
And then over here I'll change it to.
Off, and I'm just going to save.
Okay, Now let's just test this out.
If I log in as John, remember, John is not an admin, so I'm going to go ahead and send with this,
this, this in the body.
Okay, so now the cookie is there.
You can see it just has a one.
So that cookie is now there and it's going to get sent with every request.
If I go to get user profile, that will now work.
However, if I go to one of the admin routes.
Why is this called new request?
That's to get all users.
Let me just say get all users.
And.
What's.
Try that.
All right.
So you can see, even though I have my cookie, right.
So I'm essentially logged in.
It says not authorized as admin because John Doe is not an admin.
Now if I delete that cookie, so if I click right here and I get rid of the JWT cookie.
That's not going to work at all because I'm not logged in whatsoever.
But if I go back to my auth so auth user and instead I log in as admin.
Okay, let's do that.
Now we have a cookie and we're logged in as admin.
If I go back to get all users and I send now it works because I'm logged in as an admin.
So you can see we have our back end authentication workflow working just fine.
So what we'll do next is create our log out so that we can clear the cookie without actually having
to do this in Postman.