- 00:00:01 welcome back to this series in the last
- 00:00:04 two videos we added user signup and user
- 00:00:07 login in this video I want to make sure
- 00:00:10 that we can also protect routes we got
- 00:00:14 that token which we issue since the last
- 00:00:16 video that token we can store on our
- 00:00:19 client not want to make sure that we can
- 00:00:21 use that token to access certain routes
- 00:00:24 on our back-end that are protected
- 00:00:26 before that we need to add protection to
- 00:00:28 some of these routes first so let's do
- 00:00:30 all of that in this video
- 00:00:35 time to add some protection we got our
- 00:00:38 products and we got our order routes
- 00:00:40 here right now there are some routes
- 00:00:43 which we don't want to protect for
- 00:00:45 example getting all products that makes
- 00:00:48 sense to be an unprotected route because
- 00:00:50 if we were to create a front-end for our
- 00:00:53 shop here we probably want to be able to
- 00:00:55 present all our products even to an
- 00:00:57 authenticated users the same is true for
- 00:01:00 the get route to a specific product
- 00:01:03 typically we want to allow the user to
- 00:01:05 get more product information before he
- 00:01:07 has to sign up and that maybe buy it or
- 00:01:10 whatever the plan is however other
- 00:01:12 routes like creating a new product or
- 00:01:16 deleting products or changing products
- 00:01:19 and maybe all order related routes
- 00:01:21 including the GATT roads here are
- 00:01:23 protected routes we want to make sure
- 00:01:25 that not every user can access them and
- 00:01:28 therefore we need some way of protecting
- 00:01:31 these routes a good approach would be to
- 00:01:34 add some kind of middleware which we can
- 00:01:37 easily add to a given route that runs
- 00:01:41 prior to that route getting processed to
- 00:01:44 actually determine does it make sense to
- 00:01:46 continue or aren't you Afeni cated
- 00:01:48 anyways so we need to add some
- 00:01:51 middleware that checks for a valid token
- 00:01:54 to be there and only if the token is
- 00:01:57 there and valid can be verified so it
- 00:01:59 hasn't been filled around with on the
- 00:02:01 client only if that is the case we
- 00:02:04 continue so that's the plan we'll add
- 00:02:06 such a middleware for this I'll create a
- 00:02:08 new folder in my API folder I'll need a
- 00:02:11 name it middleware you could name it off
- 00:02:13 whatever you want and in there I'll make
- 00:02:16 add my check off J's file because this
- 00:02:20 is what I want to do I want to check
- 00:02:21 whether the user is authenticated or not
- 00:02:23 I'll start with module exports to export
- 00:02:26 something and that something is going to
- 00:02:28 be a Aero function where I get the
- 00:02:30 request response and next you probably
- 00:02:33 know this pattern it's the default
- 00:02:35 middleware pattern we use in Express
- 00:02:37 Apps now I just want to create this
- 00:02:39 function and export it in this file so
- 00:02:42 that I can import it in my order and
- 00:02:45 product route file and then use it in
- 00:02:47 there to add
- 00:02:48 to certain routes if you remember in the
- 00:02:52 product route here we have the post
- 00:02:54 route where we also have that upload
- 00:02:57 signal middleware which will parse a
- 00:03:00 file and this is exactly the same
- 00:03:02 pattern I want to use we can add as many
- 00:03:05 handlers as we want and they will be
- 00:03:08 executed in the order from left to right
- 00:03:10 so if I then add my check-off middleware
- 00:03:13 here I will actually run through that
- 00:03:15 first and only continue if we succeed
- 00:03:17 that's the plan now for that will create
- 00:03:19 it here now what do we have to do in
- 00:03:22 this file we have to call next if we did
- 00:03:27 successfully authenticate and we want to
- 00:03:30 not call it we want to return an error
- 00:03:32 instead if we did not succeed so for
- 00:03:36 that we need some information from the
- 00:03:38 JWT package or we need some help from
- 00:03:41 that package we used in the last videos
- 00:03:43 there we have a way of creating a token
- 00:03:46 now there all this a verify method which
- 00:03:49 allows us to verify an incoming token
- 00:03:51 that is what I mentioned in the last
- 00:03:52 videos the server can verify whether a
- 00:03:56 token is valid or not for that of course
- 00:03:58 we need to that key we stored on the
- 00:04:00 server and we need to token so let's do
- 00:04:04 just that
- 00:04:05 let's import this JSON web token package
- 00:04:08 in this file here so I'll create my JWT
- 00:04:11 constant and simply require JSON web
- 00:04:14 token and then in there I will simply
- 00:04:20 create a new concept which I named
- 00:04:22 decoded because the verify method will
- 00:04:26 actually return the decoded token if it
- 00:04:28 succeeds and then I will call JWT verify
- 00:04:33 now you might see there are always a
- 00:04:35 decode method this will just decode the
- 00:04:38 token and not verify it and as I
- 00:04:40 mentioned in the last video the token is
- 00:04:42 not encrypted so decoding alone doesn't
- 00:04:45 ensure it's valid it just ensures its
- 00:04:47 valid base64 encoding but that doesn't
- 00:04:50 help us
- 00:04:51 so decode is only helpful if you want to
- 00:04:54 get to the internals of the token after
- 00:04:57 having verified it if you didn't verify
- 00:05:00 it yet then decode
- 00:05:02 makes no sense and verify we'll do both
- 00:05:04 verify it and then return the decoded
- 00:05:07 value so here is what I'll use
- 00:05:09 verify and then I assume to get to token
- 00:05:13 as part of the request body if we don't
- 00:05:16 well then we will always fail here and
- 00:05:19 that is exactly what we want to do if we
- 00:05:21 go into this middleware which we only do
- 00:05:24 if we added it to a route if we go in
- 00:05:27 here and there is no token present then
- 00:05:30 we should fail because then we got note
- 00:05:32 Okin right so we pass the token here the
- 00:05:38 key is what we stored in our environment
- 00:05:40 variables to process end and then it was
- 00:05:42 JWT key in my case here I added this in
- 00:05:45 the last video and then the next
- 00:05:48 argument are some options I don't pass
- 00:05:50 any special options here and then a
- 00:05:53 callback you can specify so I will omit
- 00:05:55 the last two values here I just want to
- 00:05:58 verify it like this now this method
- 00:06:01 verify will actually throw an error if
- 00:06:03 it fails so what I'll do is I'll add a
- 00:06:06 try-catch block here I'll try decoding
- 00:06:10 the token so I'll try this code here but
- 00:06:13 if I fail then I will catch my error and
- 00:06:19 in here I will then return a response
- 00:06:23 where I set the status code to 401 on an
- 00:06:27 authenticated and return a JSON object
- 00:06:29 with the message off failed just like
- 00:06:33 that
- 00:06:34 if we succeed here in the try block
- 00:06:37 though then we got a decoded value and I
- 00:06:42 will eventually call Next to continue
- 00:06:44 and what I also can do is I can set
- 00:06:47 request user data equal to decoded so
- 00:06:52 I'm adding a new field to my request
- 00:06:54 make sure to pick one which you don't
- 00:06:56 accidentally which you don't already
- 00:06:58 have so that you don't overwrite it and
- 00:07:00 now in future requests which use these
- 00:07:03 map that this middle where in front of
- 00:07:04 it we could extract a user data the
- 00:07:06 decoded user data on that field now with
- 00:07:10 that we get a middle where let's now try
- 00:07:12 it out and let's go to the products
- 00:07:15 file a page maybe and let's add it to
- 00:07:18 the post product route so GAD should be
- 00:07:21 publicly accessible but we want to add
- 00:07:24 our middleware to the post route so I'll
- 00:07:27 first of all import it I'll add and you
- 00:07:29 can't set the top here check off and I
- 00:07:32 will require it from middleware check
- 00:07:36 off and this is now the function we're
- 00:07:39 exporting there which is a valid
- 00:07:41 middleware function and now in the post
- 00:07:43 route here I will simply add check off
- 00:07:46 in front of this upload single and the
- 00:07:51 other handlers so this will run first
- 00:07:53 I don't execute it I will just edit like
- 00:07:57 this and Express will automatically pass
- 00:07:59 requests and so on into this now let's
- 00:08:01 try it out let's go back to postman and
- 00:08:04 let's create a new post request to
- 00:08:07 products let's switch to foreign data
- 00:08:11 again and make sure you enter your valid
- 00:08:13 data here and choose a file I added a
- 00:08:16 very Christmasy file here again and
- 00:08:19 let's now simply try this out let's now
- 00:08:22 hit send and first of all go to headers
- 00:08:26 and disable this content type and hits
- 00:08:29 send again and we get all failed because
- 00:08:32 the token is missing we're checking if
- 00:08:35 we got a token in the body
- 00:08:38 so let's simply add one let's first of
- 00:08:41 all make sure we can login I'll create a
- 00:08:44 new tab with a post request again queue
- 00:08:49 localhost
- 00:08:52 3000 slash user slash login and asked
- 00:08:58 before I'll add a header here content
- 00:09:01 type application Jason and a body raw
- 00:09:09 JSON data where I will set an email
- 00:09:13 password combination that exists in
- 00:09:15 database well again use test free at
- 00:09:17 test calm and your password was tester
- 00:09:22 now if we use that and we sent this
- 00:09:24 request I get my token so I'll copy that
- 00:09:27 and now go back to the first tab where
- 00:09:30 I'm setting the post request to products
- 00:09:32 and I'll add my token key here and add
- 00:09:35 token as a value I now hit Send I still
- 00:09:39 get all failed though now it can be
- 00:09:42 difficult to find out why the reason is
- 00:09:45 that in this post route remember we're
- 00:09:47 getting full and data were not getting
- 00:09:49 JSON data now in the app J's file we
- 00:09:53 only get body parsers for URL encoded
- 00:09:56 and JSON content type requests neither
- 00:10:00 is the case here we got form data and
- 00:10:02 we're taking care about this with the
- 00:10:04 upload single mail aware which simply
- 00:10:06 parses form data requests and extracts
- 00:10:10 the file along the way but it does this
- 00:10:12 parsing since check off runs prior to
- 00:10:15 this request body will not be populated
- 00:10:19 because it hasn't been parsed yet
- 00:10:21 now one workaround of course is to
- 00:10:23 switch the order here we can put check
- 00:10:26 off as the second middleware if we do
- 00:10:29 this and ahead send here then we do
- 00:10:32 simply a continue we just fail with the
- 00:10:35 creation of the uploads directory here
- 00:10:38 because I deleted that in the meantime I
- 00:10:40 would have to re-add it if I do that
- 00:10:44 uploads
- 00:10:48 and I had send again it succeeds and we
- 00:10:53 can see the file here then so then it
- 00:10:56 works this is one way changing the order
- 00:10:58 yeah we can do this we're doing some
- 00:11:01 unnecessary work here with the parsing
- 00:11:03 since we don't check prior to it if we
- 00:11:06 are authenticated and in general we
- 00:11:09 might not want to pass the token as part
- 00:11:12 of the request body because what do we
- 00:11:14 do for get requests sure we could add it
- 00:11:17 to the URL in a query parent or example
- 00:11:20 and we can't do all of that but a
- 00:11:22 typical pattern is to put the token into
- 00:11:25 the header so I'll remove this key here
- 00:11:28 I don't want to send to token like this
- 00:11:30 I want to send it as part of my headers
- 00:11:33 and there's one common header we use for
- 00:11:35 this the authorization header
- 00:11:38 authorization as the name implies should
- 00:11:40 hold any information we need for
- 00:11:42 authorizing a request and there a token
- 00:11:45 is typically sent by adding bearer
- 00:11:48 whitespace and then the token so the
- 00:11:52 token you previously previously sent
- 00:11:54 here in the request bodies let me copy
- 00:11:57 it again
- 00:11:57 and put it here after Bearer now why
- 00:12:01 bearer notice is simply a convention
- 00:12:04 used to indicate that this authorization
- 00:12:06 header bears a token it's basically an
- 00:12:09 alternative to basic HTTP authentication
- 00:12:11 so hence bearer the tokens of course the
- 00:12:14 interesting part with this setup we
- 00:12:16 don't need to parse the body to get the
- 00:12:18 token we just need to have a look at the
- 00:12:20 header so in check off we now get to
- 00:12:24 token from the header so I'll first of
- 00:12:27 all simply try to get my token from the
- 00:12:30 header and I can do this by accessing
- 00:12:32 request header a headers authorization
- 00:12:38 if I do this let's simply lock to token
- 00:12:41 here if I now again sent my post request
- 00:12:45 to create a product it now fails here
- 00:12:49 because I removed the token from the
- 00:12:51 from the body remember I unchecked this
- 00:12:54 year I'm no longer sending it so it
- 00:12:57 fails in the console log we see this out
- 00:13:00 though so we did successfully parse the
- 00:13:02 header and that of course means we can
- 00:13:05 now use the token from there we just
- 00:13:06 have to make sure that we don't include
- 00:13:08 the bearer and the whitespace so what
- 00:13:10 I'll actually do is I'll get my request
- 00:13:13 headers authorization and split it by a
- 00:13:17 white space I then access the first
- 00:13:21 segment where the second one actually
- 00:13:23 with index one which will be this part
- 00:13:25 after the white space and then I can
- 00:13:28 pass my token here to the verify method
- 00:13:31 all safe doesn't go back to products and
- 00:13:33 now revert the order here again so I'll
- 00:13:37 now add check off prior to trying to
- 00:13:40 parse the body here
- 00:13:41 and now if we save this make sure that
- 00:13:44 authorization is set to your token with
- 00:13:46 bearer in front of it and if I try to
- 00:13:48 send us again it now succeeds if I
- 00:13:52 change to token by for example removing
- 00:13:54 the e and therefore all basically send
- 00:13:56 an invalid token it fails and this is a
- 00:14:00 nice middleware we can now use to make
- 00:14:02 sure that we protect our routes let's
- 00:14:06 add it to multiple routes then instead
- 00:14:08 of just adding it in front of or in our
- 00:14:11 post route here I'll also add in the
- 00:14:14 patch route
- 00:14:15 so before we there have our main
- 00:14:17 handling function and in the delete
- 00:14:20 route not in the to cat routes as I
- 00:14:22 mentioned and the same in orders there
- 00:14:26 I will now also import my check off
- 00:14:29 middleware by requiring this from the
- 00:14:33 middleware folder check off and I will
- 00:14:36 add it there to in front of all routes
- 00:14:38 actually because all should be protected
- 00:14:40 including the GATT routes so getting all
- 00:14:43 orders posting new orders getting a
- 00:14:46 single order and deleting order
- 00:14:48 everything is now protected and now if I
- 00:14:52 save this we can try it out we train can
- 00:14:55 try getting products and this should
- 00:14:57 succeed even if we remove that header
- 00:15:00 because it's not a protected route if I
- 00:15:04 try to delete a product though for this
- 00:15:08 let me quickly get an ID like this one
- 00:15:10 so if I now add this in the URL as we
- 00:15:13 have to do it
- 00:15:14 for a delete request and I sent this
- 00:15:15 without the authorization header I get
- 00:15:18 all failed if I add the authorization
- 00:15:20 header I still get it because it's still
- 00:15:24 the invalid token so let me reverse this
- 00:15:26 by adding de again now it succeeds and
- 00:15:29 if I remove it just to prove this again
- 00:15:31 and of course fails so this is now an
- 00:15:34 option and now let's check our orders
- 00:15:36 there we can't just try to get all
- 00:15:38 orders if I don't add the token it fails
- 00:15:41 if I do add it it succeeds so this is
- 00:15:46 how we can now use the token how we did
- 00:15:48 add our middleware which we can now
- 00:15:50 conveniently add to any route that
- 00:15:52 should be protected and we're using the
- 00:15:55 tray WT concept for this authentication
- 00:15:58 flow and for making sure that the client
- 00:16:01 can identify himself to our server and
- 00:16:04 access protected resources without the
- 00:16:07 server having to store any information
- 00:16:09 about the connected clients this is now
- 00:16:11 true stateless authentication
- 00:16:14 implemented in our restful service
- 00:16:16 through JSON web tokens now with that we
- 00:16:20 made a huge step forward we added
- 00:16:23 authentication