1 00:00:00,570 --> 00:00:02,160 Instructor: We've made some major progress 2 00:00:02,160 --> 00:00:03,810 on our application here. 3 00:00:03,810 --> 00:00:05,760 We've got the ability to sign in, sign out, 4 00:00:05,760 --> 00:00:07,320 protect routes, blah, blah, blah. 5 00:00:07,320 --> 00:00:08,880 You know, we've gone over it several times, 6 00:00:08,880 --> 00:00:11,790 but there's still one very core aspect of our application 7 00:00:11,790 --> 00:00:13,740 that we haven't addressed at all. 8 00:00:13,740 --> 00:00:15,570 I'm gonna pull up the code for our server 9 00:00:15,570 --> 00:00:18,930 that we had written previously, specifically the router. 10 00:00:18,930 --> 00:00:20,340 So if you recall, inside of our router 11 00:00:20,340 --> 00:00:22,830 we had this root route right here, 12 00:00:22,830 --> 00:00:26,460 and the only response to that root route was a message. 13 00:00:26,460 --> 00:00:28,260 And we were sending back a string right here. 14 00:00:28,260 --> 00:00:32,759 So message, super secret code is ABC123. 15 00:00:32,759 --> 00:00:35,880 That kinda twist about this route is that we protected it 16 00:00:35,880 --> 00:00:38,280 with this requireAuth middleware right here. 17 00:00:38,280 --> 00:00:39,817 So this requireAuth said, 18 00:00:39,817 --> 00:00:42,187 "Hey, if someone is trying to access this route 19 00:00:42,187 --> 00:00:44,677 "we need to verify that they have a correct 20 00:00:44,677 --> 00:00:48,480 "and valid JWT token attached to the request." 21 00:00:48,480 --> 00:00:50,070 So this was really the whole impetus 22 00:00:50,070 --> 00:00:52,680 behind talking about authentication. 23 00:00:52,680 --> 00:00:55,410 Not only do we want users to be able to sign in and sign up, 24 00:00:55,410 --> 00:00:56,910 but we also wanted to make sure 25 00:00:56,910 --> 00:01:00,060 that they could get access to very particular routes 26 00:01:00,060 --> 00:01:03,693 inside the application that were secured by the JWT token. 27 00:01:04,560 --> 00:01:06,180 So this is the last part of the application 28 00:01:06,180 --> 00:01:07,440 that we need to work on. 29 00:01:07,440 --> 00:01:09,540 We need to make sure that after a user signs in, 30 00:01:09,540 --> 00:01:12,240 they can make an authenticated request. 31 00:01:12,240 --> 00:01:14,400 So this is where the JWT on the client side 32 00:01:14,400 --> 00:01:15,990 is gonna come into play. 33 00:01:15,990 --> 00:01:18,210 Up until this point, we've really been pretty 34 00:01:18,210 --> 00:01:22,860 kinda ignored the JWT token altogether, I would nearly say. 35 00:01:22,860 --> 00:01:25,440 Sure, we kinda picked it up and we saved it, 36 00:01:25,440 --> 00:01:28,110 and we kind of used it to decide whether or not the user 37 00:01:28,110 --> 00:01:29,340 is currently logged in. 38 00:01:29,340 --> 00:01:31,860 But we haven't really used the token itself 39 00:01:31,860 --> 00:01:33,900 to make any type of request or anything. 40 00:01:33,900 --> 00:01:35,250 And so now we're gonna go into the realm 41 00:01:35,250 --> 00:01:38,013 of the JWT token itself. 42 00:01:39,840 --> 00:01:42,450 So again, the token's purpose is to be able to make 43 00:01:42,450 --> 00:01:44,850 authenticated requests to our API server. 44 00:01:44,850 --> 00:01:47,190 And so to get a really good example of this going, 45 00:01:47,190 --> 00:01:49,170 we're going to eventually need to put together 46 00:01:49,170 --> 00:01:52,050 some type of request to reach out to that root route 47 00:01:52,050 --> 00:01:53,340 on our server. 48 00:01:53,340 --> 00:01:55,113 The... Oops, just lost it. 49 00:01:56,280 --> 00:01:58,890 There it is. The root route right here. 50 00:01:58,890 --> 00:01:59,790 So this is our goal. 51 00:01:59,790 --> 00:02:02,670 We want to make an Ajax request to this root route 52 00:02:02,670 --> 00:02:04,560 and we want to make sure that we send along 53 00:02:04,560 --> 00:02:06,810 our JWT token as well. 54 00:02:06,810 --> 00:02:09,570 So here's gonna be the kinda the order of operations here. 55 00:02:09,570 --> 00:02:11,160 Here's how we're gonna tackle it. 56 00:02:11,160 --> 00:02:14,160 First, we're gonna make an action creator to make a request. 57 00:02:14,160 --> 00:02:15,540 So we're just gonna make an action creator, 58 00:02:15,540 --> 00:02:17,490 we're just gonna make the request. 59 00:02:17,490 --> 00:02:19,440 We're gonna hook this action creator up 60 00:02:19,440 --> 00:02:21,000 to our feature component. 61 00:02:21,000 --> 00:02:22,530 And remember, the feature component right now 62 00:02:22,530 --> 00:02:25,083 is pretty empty, pretty straightforward. 63 00:02:27,089 --> 00:02:27,922 Once we get it hooked up, 64 00:02:27,922 --> 00:02:30,630 we're not gonna send along the JWT token. 65 00:02:30,630 --> 00:02:32,790 Instead, we're just gonna take a look at the request 66 00:02:32,790 --> 00:02:34,860 and see kinda what happens 67 00:02:34,860 --> 00:02:36,090 when we don't send the token along? 68 00:02:36,090 --> 00:02:37,950 What type of irresponse or error message 69 00:02:37,950 --> 00:02:39,480 do we get from our server? 70 00:02:39,480 --> 00:02:41,280 And then we'll go back and revise the request 71 00:02:41,280 --> 00:02:43,140 to include the token as well. 72 00:02:43,140 --> 00:02:44,640 So let's give is a shot. 73 00:02:44,640 --> 00:02:46,290 Like I said, the first thing we're gonna be doing 74 00:02:46,290 --> 00:02:50,190 is going to make an action creator for making the request. 75 00:02:50,190 --> 00:02:54,543 I'm going to export a function called fetchMessage. 76 00:02:56,010 --> 00:02:59,190 We're going to use Redux Thunk again. 77 00:02:59,190 --> 00:03:03,120 So I'm going to return a function that's called dispatch. 78 00:03:03,120 --> 00:03:05,190 Keep in mind here that we could have just as easily 79 00:03:05,190 --> 00:03:08,190 used redux-promise for this part. 80 00:03:08,190 --> 00:03:09,750 We're just making a very simple, 81 00:03:09,750 --> 00:03:11,640 very straightforward Ajax request 82 00:03:11,640 --> 00:03:13,200 just to get some JSON. 83 00:03:13,200 --> 00:03:15,240 So we could definitely use redux-promise here 84 00:03:15,240 --> 00:03:17,700 just to stay consistent with the rest of our app. 85 00:03:17,700 --> 00:03:20,610 We're gonna continue making use of Redux Thunk. 86 00:03:20,610 --> 00:03:22,590 The two of them, I wouldn't say necessarily 87 00:03:22,590 --> 00:03:25,410 are mutually exclusive, but definitely if you have one, 88 00:03:25,410 --> 00:03:28,473 you tend to not really need to make use of the other. 89 00:03:29,970 --> 00:03:33,000 So inside of this Redux Thunk function, 90 00:03:33,000 --> 00:03:37,020 I'm gonna make a GET request to the root URL. 91 00:03:37,020 --> 00:03:39,240 And if you recall, the root URL 92 00:03:39,240 --> 00:03:41,250 was defined at the top of our page 93 00:03:41,250 --> 00:03:43,110 as just local host 3090. 94 00:03:43,110 --> 00:03:45,120 So this really is like a request 95 00:03:45,120 --> 00:03:46,770 to the root route on our API. 96 00:03:46,770 --> 00:03:50,370 I would expect that this request right here 97 00:03:50,370 --> 00:03:52,140 should show me the message, 98 00:03:52,140 --> 00:03:54,603 super secret code is ABC123. 99 00:03:55,830 --> 00:03:56,730 Let's actually test that out. 100 00:03:56,730 --> 00:03:58,800 I'm gonna take off the semicolon. 101 00:03:58,800 --> 00:04:01,410 Let's put on a .then case. 102 00:04:01,410 --> 00:04:04,020 And we'll say that when we get the response 103 00:04:04,020 --> 00:04:07,350 I want to console log the entire response. 104 00:04:07,350 --> 00:04:09,503 So let's just see what we get out of this thing. 105 00:04:10,440 --> 00:04:11,910 We've now got an action creator, 106 00:04:11,910 --> 00:04:14,070 but it needs to be actually called somewhere. 107 00:04:14,070 --> 00:04:15,600 As I mentioned, we're gonna be using 108 00:04:15,600 --> 00:04:17,130 the Feature component for that. 109 00:04:17,130 --> 00:04:19,230 So let's pull open Feature. 110 00:04:19,230 --> 00:04:21,899 Now inside of Feature, if we want to call an action creator, 111 00:04:21,899 --> 00:04:24,733 we're going to need to import our actions, 112 00:04:24,733 --> 00:04:28,320 and react-redux as well, the Connect helper. 113 00:04:28,320 --> 00:04:30,330 So let's do both of those. 114 00:04:30,330 --> 00:04:34,500 I'll import connect from react-redux, 115 00:04:34,500 --> 00:04:39,500 and I'll also import star as actions from up actions. 116 00:04:43,320 --> 00:04:44,700 There we go. 117 00:04:44,700 --> 00:04:47,220 Then we'll use our connect helper. 118 00:04:47,220 --> 00:04:49,440 We're not gonna be making use of map state 119 00:04:49,440 --> 00:04:50,490 to props just yet. 120 00:04:50,490 --> 00:04:53,010 So I'll throw a null in there, 121 00:04:53,010 --> 00:04:55,050 actions as our second argument. 122 00:04:55,050 --> 00:04:57,030 And now to call the actual action creator, 123 00:04:57,030 --> 00:04:59,420 let's hook up our component, willMount. 124 00:05:00,900 --> 00:05:02,430 So as soon as this component is about 125 00:05:02,430 --> 00:05:04,140 to be rendered to the screen, 126 00:05:04,140 --> 00:05:05,790 we will call our action creator 127 00:05:05,790 --> 00:05:08,793 this.props.fetchMessage. 128 00:05:10,380 --> 00:05:12,150 Cool. So this should probably be enough 129 00:05:12,150 --> 00:05:13,440 to make our Ajax request. 130 00:05:13,440 --> 00:05:15,540 And just kinda see what happens 131 00:05:15,540 --> 00:05:18,090 when we don't include our JWT token hearing. 132 00:05:18,090 --> 00:05:20,820 Remember, the token is not included by default. 133 00:05:20,820 --> 00:05:22,740 It is something that we very specifically 134 00:05:22,740 --> 00:05:24,120 have to include with our request. 135 00:05:24,120 --> 00:05:25,590 So right now we're just saying, 136 00:05:25,590 --> 00:05:27,150 you know what, just make a request. 137 00:05:27,150 --> 00:05:28,563 Let's just see what happens. 138 00:05:29,400 --> 00:05:31,530 So I'm gonna flip over to Chrome, 139 00:05:31,530 --> 00:05:35,220 and we immediately refresh the page onto Feature. 140 00:05:35,220 --> 00:05:36,870 It looks like we're making a request here, 141 00:05:36,870 --> 00:05:38,523 which is the action creator. 142 00:05:39,480 --> 00:05:41,190 But it's returning a 401, 143 00:05:41,190 --> 00:05:43,230 and a 401 basically means unauthorized. 144 00:05:43,230 --> 00:05:45,660 You cannot get access to this content. 145 00:05:45,660 --> 00:05:47,820 So we're definitely in an error state right here, 146 00:05:47,820 --> 00:05:50,550 which is exactly what we want and what we expect. 147 00:05:50,550 --> 00:05:52,770 We definitely want to see an error message here 148 00:05:52,770 --> 00:05:55,050 when we do not include our token. 149 00:05:55,050 --> 00:05:57,330 Let's go back and revise our code now, 150 00:05:57,330 --> 00:06:00,273 and revise this request to include the token as well. 151 00:06:01,590 --> 00:06:03,960 Remember to make an authenticator request for the token, 152 00:06:03,960 --> 00:06:08,100 we're going to include it in the headers of our request. 153 00:06:08,100 --> 00:06:10,470 So to add a header with axios, 154 00:06:10,470 --> 00:06:12,750 I'm gonna take the root URL right here. 155 00:06:12,750 --> 00:06:15,450 We're gonna put an object after it. 156 00:06:15,450 --> 00:06:18,663 So I have root_URL, object. 157 00:06:19,530 --> 00:06:22,380 We're going to say, here are the headers. 158 00:06:22,380 --> 00:06:24,393 I wanna include authorization, 159 00:06:25,740 --> 00:06:27,573 and we'll pull out our token. 160 00:06:30,570 --> 00:06:31,403 Here we go. 161 00:06:32,400 --> 00:06:35,310 So the second argument for the axios.get 162 00:06:35,310 --> 00:06:38,220 is kind of a options object of sorts. 163 00:06:38,220 --> 00:06:41,310 And so we can pass in some optional headers, 164 00:06:41,310 --> 00:06:43,920 one of which will be specifically authorization, 165 00:06:43,920 --> 00:06:46,320 which is gonna be our JWT token. 166 00:06:46,320 --> 00:06:48,780 So now let's give this a shot in the browser again. 167 00:06:48,780 --> 00:06:50,430 I'm gonna refresh. 168 00:06:50,430 --> 00:06:53,910 And now it looks like we successfully did a 200 request. 169 00:06:53,910 --> 00:06:58,050 Here's the message, super secret code is ABC123. 170 00:06:58,050 --> 00:06:59,790 And I've got a data property. 171 00:06:59,790 --> 00:07:01,980 Here's the console log response right here. 172 00:07:01,980 --> 00:07:05,910 So, awesome. So this is how once our user is authenticated 173 00:07:05,910 --> 00:07:07,590 this is exactly how we're going to end up 174 00:07:07,590 --> 00:07:10,290 making an authenticated request to our backend 175 00:07:10,290 --> 00:07:12,090 using our token right here. 176 00:07:12,090 --> 00:07:15,120 This approach right here is a 100% reproducible. 177 00:07:15,120 --> 00:07:17,790 You can throw in your headers all the time 178 00:07:17,790 --> 00:07:20,250 as much as you want, just make the request. 179 00:07:20,250 --> 00:07:22,410 Just remember to include your token 180 00:07:22,410 --> 00:07:23,673 with the request as well. 181 00:07:24,870 --> 00:07:26,580 So this looks pretty good. 182 00:07:26,580 --> 00:07:29,850 It would be nice if we kind of showed the message 183 00:07:29,850 --> 00:07:32,850 that we got back, you know, that message 184 00:07:32,850 --> 00:07:34,350 in our actual feature component, 185 00:07:34,350 --> 00:07:36,990 just to bring the entire project through to completion. 186 00:07:36,990 --> 00:07:39,363 So let's go through that entire process. 187 00:07:40,680 --> 00:07:42,750 I'm going to add another case 188 00:07:42,750 --> 00:07:45,123 to the existing off reducer we have. 189 00:07:46,380 --> 00:07:48,120 The off reducer isn't really appropriate 190 00:07:48,120 --> 00:07:49,410 for putting this message in here, 191 00:07:49,410 --> 00:07:50,880 but you know, what the heck? 192 00:07:50,880 --> 00:07:53,670 Let's just, rather than go through the process 193 00:07:53,670 --> 00:07:55,020 of making a totally new reducer, 194 00:07:55,020 --> 00:07:57,810 we'll just reuse the existing one for right now. 195 00:07:57,810 --> 00:07:59,970 Let's take care of wiring up that message 196 00:07:59,970 --> 00:08:01,293 inside the next section.