Okay.
What we're going to take a look at now is using our router functionality to prevent a user from accessing
this component in the browser and adding.
And I'm going to use air quotes for this, some kind of client side security because there is no such
thing as client side security.
What we've got here is a single page JavaScript based application.
And when this application loads, then all of the JavaScript is visible and downloaded by the client
browser.
And anybody can see all of the code that makes up our client side application, including anything related
to security.
So we can't really have client side security.
All of our actual security is on our server side now that's protected with our authorization attributes.
If there's endpoints we don't want to use to get to all those data we do not want our users to see,
then that has to be protected.
On the API side of things, what we're going to do here is the equivalent of client side validation.
But from an authentication perspective, we're going to check to make sure that our users are Authorized
before they can get to this particular page.
Now, this really is just a user interface feature, and it's not really security because we can't even
check the cookie to see if the user has a cookie in their browser.
There's no way for us to get to that cookie at all from our application, so the only thing we can really
do to check is to see if we've got the user object.
And if we do, then, well, we can presume that they're authenticated and we can let them through to
the checkout component in this case.
So let's set this up on our application.
And like I say this is really just a user interface feature.
It's not security at all as all we can check for is whether or not we've got the user object inside
our Redux store, and it's cached in our store.
If it is, then we're going to say, yep, that's okay, you're logged in.
If not, we're going to redirect them to our login component.
So let's deal with this.
And inside the routes in this case in our app folder we'll create a new file and we'll just call it
require.
Or in this case TSX.
And we'll make this a react component.
So just use RFC.
And inside here we'll make use of the hook to get the user info.
So we'll use const and say data colon user equals use user info query.
And we'll also check to see if we're loading at this stage as well because it may not be in our cache.
This may be something that we need to go out and get from our API, depending on whether or not we've
refreshed or if we're coming here from an already loaded application, then possibly it could be loading.
And we're also going to use the location from React Router so that we know where the user is coming
from, so that we can redirect them back there after they have logged in.
So we'll use the use location from React Router Dom here as well.
We'll check to see if we're loading.
And if we are loading.
Then I'm just going to return a div with loading dot dot dot.
I doubt we'll ever see that.
But just in case.
And then we'll do another check and see if not user, then we will return and we'll use a component
we get from React Router called navigate.
And then we can specify two equals and we can send them to forward slash login.
And we'll pass in some states with this as well.
And we'll send in the from property and set that to be the location and give this it's self-closing
tag.
And what we return from this is we return the outlets we get from React Router Dom.
So effectively our component is loaded up in an outlet if they meet our authentication requirements,
which means, hey, they've got a user in our Redux store cache, then we'll return the outlets, which
is going to be a route that we can load from our routes.
If they're not logged in, as in we do not have the to use her.
Then we're going to redirect them to the login component and we'll see how we get on with this.
But next we need to open up our routes.
And we're going to have an element inside here where all of our protected routes, we only have one
at the moment.
The checkout page inside our children.
Inside the app we'll add curly brackets and we'll specify the elements.
And the element in this case is going to be require auth and list is going to have children.
And we'll add the colon.
Open up an array and just add the comma underneath this.
And then any routes that we wish to protect which in this case is going to be our checkout page, I'll
cut from there and paste inside here.
And that is it.
That's all we need to do to ensure that only authorized users can access our checkout page.
So let's see if this is going to work.
And I've got a not found.
But let's go back to another part of our application.
I'll just refresh the page as well just to make sure everything is fine.
I'll go to the shopping carts.
hearts.
I can see the basket.
That's great.
I'll click on checkout.
And I've been redirected to my login component.
So this part's working just fine.
And we also want to be able to redirect the user back to the checkout if that's where they've tried
to get to before we redirected them to the login.
So let's head back to VS code and we'll open up our login form to do this.
And inside here let's get the hook the use location hook that we used in the require auth.
So I'll just add it inside here and I'll say const location equals use location Sean.
And the ordering of what I've done here, I've put it in a very specific place it looks like.
But it could be at the top, it could be at the bottom.
It doesn't really matter as long as it's above where we're trying to use it, then that's fine.
And we also need to we've got the navigate inside here as well.
So that's fine.
So where we've got our navigate let's use navigate to and we'll use location dot state dot from.
Or we're going to send them to the catalog.
So I make the state dot from optional with the optional chaining there.
So if we have that then that's where we're going to send them to.
If not we're going to send them to the catalog.
So let's see if that functionality works as we'd expect it.
I'll just go back to the catalog.
I'll actually refresh the page again.
I'll go to the basket, I'll go to the checkouts.
I've been redirected to the login page.
I'll log in as bob@test.com with the password.
And what I'd hope to see is we get redirected to the checkout page.
Obviously that failed.
So there's something else awry here.
And this is somewhat of an annoying thing to fix.
And it's really a timing issue because I am logged in, but I didn't get redirected to the checkout
page.
So the way around this is because we're logging in.
Then we need to use our fetch user info also inside the login component.
So we avoid that timing issue for this one piece of functionality.
Now we're not going to make multiple requests to go and get the user info when we're using RTK query.
Caching is a thing, and if it has the cache data, that's the data it's going to use.
But what we're going to do here is just make sure we've checked to see the user info before we move
on to the next step, which is to redirect them.
So back to our login form and let's open up our login form.
And after we've logged in let's also bring in the fetch user info.
So I'll say const in square brackets fetch user info and we'll say equals use.
Lazy use user info query.
We need the lazy version of this.
So I've got the use user info query.
But we need the other version.
So let's go back to our accounts API and as well as the use user info query.
Let's just drop that down to the next line and tidy that up.
And I'll also use the use lazy user info query.
And this is the one that we'll utilize in our login form.
So in our login form let's use the lazy user info query.
And after we've logged in we'll say await and fetch user info.
And let's go and see if this has got the desired effect.
So I'll go back to the.
In fact I'll need to log out of Bob first of all.
And I'll just refresh the page once again.
And I've still got my basket.
So that's not affected by whether or not we log in or log out.
I'll go back to the shopping cart, go to the checkout, try and log in as Bob once again with the password.
And what should happen this time is we get redirected to our checkout component.
So slightly annoying to fix that, but fix that it does.
And now we've got our Functionality working.
I don't like the font in the user menu, so this is something else I'm just going to change before we
wrap up this section, because this is the last activity we're doing inside this section.
So I just want to make this a bit bigger because that's tiny.
And I'll head back to VS code to take care of that.
And we'll just go to our user menu and where we've got the button.
Let's give this some properties and we'll make the color consistent with the other elements here as
well.
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
property and give it a font size of 1.1 in quotes I need this in 1.1.
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
on with the rest of this.
And we can see our different options there, which looks fine as well.
So great.
Now we've dealt with identity.
We've got a secure way for our users to log in.
We're able to check to see they're logged in from our client browser as well.
And we can also secure our API endpoints behind authentication as well.
And all of that, even though it's not too much work, it doesn't feel like we've done much to get this
accomplished, but that's because we're using the off the shelf, if you like, authentication system
provided by ASP.Net identity, but that doesn't mean it's not secure.
And short of offloading identity to an identity provider, that's probably as good as we can get it
on an application like this.
So that's the end of this section.
So let's close all of the open tabs down.
I'll head over to the Source Control tab.
We'll stage our changes here.
And I'll just say end of section nine as the commit message.
I'll commit and then sync these changes up with GitHub.
And we'll wrap up with a summary.