WEBVTT

00:00.020 --> 00:00.350
Okay.

00:00.350 --> 00:05.540
What we're going to take a look at now is using our router functionality to prevent a user from accessing

00:05.540 --> 00:09.560
this component in the browser and adding.

00:09.560 --> 00:14.690
And I'm going to use air quotes for this, some kind of client side security because there is no such

00:14.690 --> 00:16.040
thing as client side security.

00:16.070 --> 00:19.730
What we've got here is a single page JavaScript based application.

00:19.730 --> 00:27.020
And when this application loads, then all of the JavaScript is visible and downloaded by the client

00:27.020 --> 00:27.890
browser.

00:27.890 --> 00:34.970
And anybody can see all of the code that makes up our client side application, including anything related

00:34.970 --> 00:35.870
to security.

00:35.870 --> 00:38.600
So we can't really have client side security.

00:38.600 --> 00:44.750
All of our actual security is on our server side now that's protected with our authorization attributes.

00:44.750 --> 00:49.910
If there's endpoints we don't want to use to get to all those data we do not want our users to see,

00:49.940 --> 00:51.470
then that has to be protected.

00:51.470 --> 00:57.380
On the API side of things, what we're going to do here is the equivalent of client side validation.

00:57.380 --> 01:03.230
But from an authentication perspective, we're going to check to make sure that our users are Authorized

01:03.230 --> 01:05.900
before they can get to this particular page.

01:05.930 --> 01:11.540
Now, this really is just a user interface feature, and it's not really security because we can't even

01:11.540 --> 01:15.650
check the cookie to see if the user has a cookie in their browser.

01:15.680 --> 01:21.170
There's no way for us to get to that cookie at all from our application, so the only thing we can really

01:21.170 --> 01:23.840
do to check is to see if we've got the user object.

01:23.840 --> 01:29.600
And if we do, then, well, we can presume that they're authenticated and we can let them through to

01:29.630 --> 01:31.940
the checkout component in this case.

01:31.940 --> 01:36.350
So let's set this up on our application.

01:36.350 --> 01:39.320
And like I say this is really just a user interface feature.

01:39.320 --> 01:44.870
It's not security at all as all we can check for is whether or not we've got the user object inside

01:44.870 --> 01:47.660
our Redux store, and it's cached in our store.

01:47.660 --> 01:50.300
If it is, then we're going to say, yep, that's okay, you're logged in.

01:50.330 --> 01:53.930
If not, we're going to redirect them to our login component.

01:53.930 --> 01:55.850
So let's deal with this.

01:55.850 --> 02:04.580
And inside the routes in this case in our app folder we'll create a new file and we'll just call it

02:04.640 --> 02:05.510
require.

02:07.820 --> 02:10.880
Or in this case TSX.

02:10.880 --> 02:13.340
And we'll make this a react component.

02:13.340 --> 02:14.810
So just use RFC.

02:15.680 --> 02:20.600
And inside here we'll make use of the hook to get the user info.

02:20.840 --> 02:28.400
So we'll use const and say data colon user equals use user info query.

02:28.430 --> 02:33.830
And we'll also check to see if we're loading at this stage as well because it may not be in our cache.

02:33.950 --> 02:39.080
This may be something that we need to go out and get from our API, depending on whether or not we've

02:39.080 --> 02:47.000
refreshed or if we're coming here from an already loaded application, then possibly it could be loading.

02:47.000 --> 02:52.400
And we're also going to use the location from React Router so that we know where the user is coming

02:52.400 --> 02:55.970
from, so that we can redirect them back there after they have logged in.

02:55.970 --> 03:01.100
So we'll use the use location from React Router Dom here as well.

03:01.160 --> 03:02.990
We'll check to see if we're loading.

03:02.990 --> 03:04.070
And if we are loading.

03:04.070 --> 03:07.520
Then I'm just going to return a div with loading dot dot dot.

03:07.550 --> 03:08.690
I doubt we'll ever see that.

03:08.690 --> 03:10.040
But just in case.

03:10.070 --> 03:18.710
And then we'll do another check and see if not user, then we will return and we'll use a component

03:18.710 --> 03:21.290
we get from React Router called navigate.

03:23.150 --> 03:28.460
And then we can specify two equals and we can send them to forward slash login.

03:28.520 --> 03:32.120
And we'll pass in some states with this as well.

03:32.120 --> 03:39.620
And we'll send in the from property and set that to be the location and give this it's self-closing

03:39.650 --> 03:40.400
tag.

03:40.430 --> 03:49.790
And what we return from this is we return the outlets we get from React Router Dom.

03:49.820 --> 03:56.810
So effectively our component is loaded up in an outlet if they meet our authentication requirements,

03:56.810 --> 04:03.800
which means, hey, they've got a user in our Redux store cache, then we'll return the outlets, which

04:03.800 --> 04:07.190
is going to be a route that we can load from our routes.

04:07.580 --> 04:09.950
If they're not logged in, as in we do not have the to use her.

04:09.980 --> 04:14.330
Then we're going to redirect them to the login component and we'll see how we get on with this.

04:14.330 --> 04:16.820
But next we need to open up our routes.

04:17.570 --> 04:23.300
And we're going to have an element inside here where all of our protected routes, we only have one

04:23.330 --> 04:24.080
at the moment.

04:24.110 --> 04:27.560
The checkout page inside our children.

04:27.560 --> 04:32.060
Inside the app we'll add curly brackets and we'll specify the elements.

04:32.360 --> 04:38.330
And the element in this case is going to be require auth and list is going to have children.

04:38.330 --> 04:39.680
And we'll add the colon.

04:39.680 --> 04:43.310
Open up an array and just add the comma underneath this.

04:43.310 --> 04:48.860
And then any routes that we wish to protect which in this case is going to be our checkout page, I'll

04:48.860 --> 04:51.620
cut from there and paste inside here.

04:51.710 --> 04:52.850
And that is it.

04:52.850 --> 04:58.880
That's all we need to do to ensure that only authorized users can access our checkout page.

04:59.210 --> 05:00.830
So let's see if this is going to work.

05:00.860 --> 05:02.570
And I've got a not found.

05:02.570 --> 05:05.870
But let's go back to another part of our application.

05:05.870 --> 05:09.590
I'll just refresh the page as well just to make sure everything is fine.

05:09.620 --> 05:11.690
I'll go to the shopping carts.

05:11.690 --> 05:11.690
hearts.

05:11.720 --> 05:12.950
I can see the basket.

05:12.980 --> 05:13.730
That's great.

05:13.760 --> 05:15.170
I'll click on checkout.

05:15.200 --> 05:17.930
And I've been redirected to my login component.

05:17.930 --> 05:19.640
So this part's working just fine.

05:19.640 --> 05:23.750
And we also want to be able to redirect the user back to the checkout if that's where they've tried

05:23.750 --> 05:26.270
to get to before we redirected them to the login.

05:26.270 --> 05:31.130
So let's head back to VS code and we'll open up our login form to do this.

05:31.130 --> 05:38.660
And inside here let's get the hook the use location hook that we used in the require auth.

05:38.660 --> 05:47.900
So I'll just add it inside here and I'll say const location equals use location Sean.

05:48.680 --> 05:52.550
And the ordering of what I've done here, I've put it in a very specific place it looks like.

05:52.550 --> 05:55.010
But it could be at the top, it could be at the bottom.

05:55.040 --> 05:59.930
It doesn't really matter as long as it's above where we're trying to use it, then that's fine.

06:00.740 --> 06:04.250
And we also need to we've got the navigate inside here as well.

06:04.250 --> 06:04.850
So that's fine.

06:04.850 --> 06:13.370
So where we've got our navigate let's use navigate to and we'll use location dot state dot from.

06:14.800 --> 06:16.960
Or we're going to send them to the catalog.

06:16.960 --> 06:20.920
So I make the state dot from optional with the optional chaining there.

06:21.130 --> 06:24.070
So if we have that then that's where we're going to send them to.

06:24.100 --> 06:27.580
If not we're going to send them to the catalog.

06:27.610 --> 06:30.700
So let's see if that functionality works as we'd expect it.

06:30.700 --> 06:31.960
I'll just go back to the catalog.

06:31.960 --> 06:33.910
I'll actually refresh the page again.

06:34.240 --> 06:38.050
I'll go to the basket, I'll go to the checkouts.

06:38.050 --> 06:40.420
I've been redirected to the login page.

06:40.450 --> 06:45.250
I'll log in as bob@test.com with the password.

06:45.700 --> 06:50.080
And what I'd hope to see is we get redirected to the checkout page.

06:50.290 --> 06:52.360
Obviously that failed.

06:52.840 --> 06:55.450
So there's something else awry here.

06:55.450 --> 06:59.110
And this is somewhat of an annoying thing to fix.

06:59.110 --> 07:04.660
And it's really a timing issue because I am logged in, but I didn't get redirected to the checkout

07:04.660 --> 07:05.320
page.

07:05.320 --> 07:10.240
So the way around this is because we're logging in.

07:10.300 --> 07:17.470
Then we need to use our fetch user info also inside the login component.

07:17.470 --> 07:20.620
So we avoid that timing issue for this one piece of functionality.

07:20.650 --> 07:25.480
Now we're not going to make multiple requests to go and get the user info when we're using RTK query.

07:25.510 --> 07:30.310
Caching is a thing, and if it has the cache data, that's the data it's going to use.

07:30.310 --> 07:34.930
But what we're going to do here is just make sure we've checked to see the user info before we move

07:34.930 --> 07:37.450
on to the next step, which is to redirect them.

07:37.450 --> 07:42.820
So back to our login form and let's open up our login form.

07:42.820 --> 07:47.050
And after we've logged in let's also bring in the fetch user info.

07:47.050 --> 07:54.490
So I'll say const in square brackets fetch user info and we'll say equals use.

07:56.560 --> 08:00.340
Lazy use user info query.

08:00.370 --> 08:02.200
We need the lazy version of this.

08:02.200 --> 08:04.870
So I've got the use user info query.

08:04.870 --> 08:06.760
But we need the other version.

08:06.760 --> 08:14.620
So let's go back to our accounts API and as well as the use user info query.

08:14.620 --> 08:18.880
Let's just drop that down to the next line and tidy that up.

08:18.880 --> 08:23.230
And I'll also use the use lazy user info query.

08:23.290 --> 08:26.290
And this is the one that we'll utilize in our login form.

08:26.290 --> 08:33.610
So in our login form let's use the lazy user info query.

08:34.330 --> 08:40.300
And after we've logged in we'll say await and fetch user info.

08:41.530 --> 08:44.350
And let's go and see if this has got the desired effect.

08:44.350 --> 08:45.790
So I'll go back to the.

08:45.820 --> 08:48.700
In fact I'll need to log out of Bob first of all.

08:50.950 --> 08:53.620
And I'll just refresh the page once again.

08:53.620 --> 08:55.570
And I've still got my basket.

08:55.570 --> 09:00.160
So that's not affected by whether or not we log in or log out.

09:00.160 --> 09:09.250
I'll go back to the shopping cart, go to the checkout, try and log in as Bob once again with the password.

09:09.280 --> 09:15.010
And what should happen this time is we get redirected to our checkout component.

09:15.010 --> 09:18.310
So slightly annoying to fix that, but fix that it does.

09:18.340 --> 09:21.070
And now we've got our Functionality working.

09:21.070 --> 09:25.990
I don't like the font in the user menu, so this is something else I'm just going to change before we

09:26.170 --> 09:30.730
wrap up this section, because this is the last activity we're doing inside this section.

09:30.730 --> 09:33.070
So I just want to make this a bit bigger because that's tiny.

09:33.070 --> 09:35.470
And I'll head back to VS code to take care of that.

09:35.470 --> 09:40.810
And we'll just go to our user menu and where we've got the button.

09:42.190 --> 09:47.650
Let's give this some properties and we'll make the color consistent with the other elements here as

09:47.650 --> 09:47.920
well.

09:47.920 --> 09:57.130
So for the color I'll use inherits for the size of the button I'll use large and I'll just use the SE

09:57.130 --> 10:04.630
property and give it a font size of 1.1 in quotes I need this in 1.1.

10:07.750 --> 10:15.850
REM and if I go back and check that's a bit more like it, it's more in line with what we've got going

10:15.850 --> 10:17.830
on with the rest of this.

10:17.830 --> 10:21.610
And we can see our different options there, which looks fine as well.

10:21.670 --> 10:22.510
So great.

10:22.570 --> 10:24.070
Now we've dealt with identity.

10:24.100 --> 10:26.380
We've got a secure way for our users to log in.

10:26.410 --> 10:30.760
We're able to check to see they're logged in from our client browser as well.

10:31.450 --> 10:37.780
And we can also secure our API endpoints behind authentication as well.

10:37.780 --> 10:43.660
And all of that, even though it's not too much work, it doesn't feel like we've done much to get this

10:43.660 --> 10:49.870
accomplished, but that's because we're using the off the shelf, if you like, authentication system

10:49.870 --> 10:54.460
provided by ASP.Net identity, but that doesn't mean it's not secure.

10:54.490 --> 10:59.980
And short of offloading identity to an identity provider, that's probably as good as we can get it

10:59.980 --> 11:02.410
on an application like this.

11:02.410 --> 11:04.510
So that's the end of this section.

11:04.510 --> 11:08.410
So let's close all of the open tabs down.

11:08.650 --> 11:10.570
I'll head over to the Source Control tab.

11:10.570 --> 11:12.880
We'll stage our changes here.

11:12.880 --> 11:18.880
And I'll just say end of section nine as the commit message.

11:18.910 --> 11:22.660
I'll commit and then sync these changes up with GitHub.

11:22.660 --> 11:25.480
And we'll wrap up with a summary.
