WEBVTT

00:00.040 --> 00:00.320
Okay.

00:00.360 --> 00:04.600
Our next step in this training course is to think about these login and register buttons, and also

00:04.640 --> 00:10.200
the fact that we've got an area of our application that we only want authorized users to be able to

00:10.240 --> 00:14.680
access, as in people who have logged in to our application.

00:14.920 --> 00:18.080
And to do that, we're going to make use of Aspnet identity.

00:18.120 --> 00:24.880
Now, since dotnet eight, there's been a specific usage of this that's designed to secure a web API

00:24.880 --> 00:30.280
backend for Spars, a single page application, which is what we're building on our react side of things.

00:30.280 --> 00:32.480
So we'll take a look at the documentation for this.

00:32.840 --> 00:37.200
And what this gives us is effectively a lot of pre-built code.

00:37.200 --> 00:45.040
And when it does come to identity, we can create a custom version of and use identity.

00:45.080 --> 00:47.160
We can create our own user store.

00:47.160 --> 00:56.080
We can create our own password system, but that comes with a bit of work to configure it anyway.

00:56.080 --> 01:02.470
And it comes with a lot of risk because there's quite a lot involved in securing something to protect

01:02.470 --> 01:06.430
our web application from the bad people on the internet.

01:06.750 --> 01:09.830
And it's better not to do this ourselves.

01:09.830 --> 01:17.150
And it's better to use something from someone like Microsoft who do update it, who do devote resources

01:17.150 --> 01:21.110
to creating the code for this to make it as secure as possible.

01:21.550 --> 01:26.670
And the way that we're going to do this, we're going to have our dotnet application effectively being

01:26.670 --> 01:32.830
the identity store and checking the passwords to allow our users to log in.

01:33.190 --> 01:39.910
And as far as handling authentication ourselves in our own application and not offloading it to a third

01:39.910 --> 01:47.150
party like Azure, like one of the many other identity providers out there, this is probably as good

01:47.150 --> 01:52.350
as we can get for our application if we want to do everything within our application.

01:52.670 --> 01:56.270
So we're going to take a look at configuring this inside our application.

01:56.270 --> 01:59.230
And this has been available to us since dotnet eight.

01:59.230 --> 02:05.070
And we're going to use something referred to as the identity endpoints.

02:05.470 --> 02:10.470
And effectively, if we take a look at the documentation here, then it gives us, once we configure

02:10.470 --> 02:16.630
this, all of these different endpoints with not too much code.

02:17.030 --> 02:22.070
So we've got things like a register endpoint a login endpoint a refresh endpoint.

02:22.070 --> 02:26.390
If we were using JWT tokens we could refresh the token.

02:27.030 --> 02:32.270
We've got to confirm email, resend confirmation email, forgot password, reset password and so on

02:32.270 --> 02:33.030
and so on.

02:33.350 --> 02:37.910
So we get all of this functionality without needing to write the code ourselves.

02:38.390 --> 02:40.430
Is it 100% perfect for us?

02:40.470 --> 02:47.190
No, probably not, and we'll need to tweak a few things, but it's good enough for our usage and certainly

02:47.190 --> 02:50.030
good enough from a security perspective for what we're going to demonstrate here.

02:50.030 --> 02:51.870
So we're going to go and set this up.

02:51.870 --> 02:58.790
And to do that, we're going to install a package into our project for Aspnet identity.

02:58.790 --> 03:00.750
So we're going to do this on the API first of all.

03:00.750 --> 03:03.230
So we're going to go back to this solution Explorer view.

03:03.630 --> 03:06.700
But we'll open up new gates.

03:07.100 --> 03:13.180
First of all, and we're going to search for the Microsoft dot ASP.

03:13.180 --> 03:16.420
Net core dot identity.

03:17.220 --> 03:25.180
And we need the Identity Entity Framework core, because this package will allow us to create some tables

03:25.180 --> 03:28.180
in our database related to identity.

03:28.460 --> 03:36.540
So we'll go ahead and add this into our API keys proj file, which effectively adds this package into

03:36.540 --> 03:37.420
our project.

03:37.700 --> 03:42.140
And the latest one available because we're on net nine is of course dot net nine.

03:42.500 --> 03:45.460
So let's go to our entities first of all.

03:45.780 --> 03:47.540
And we're going to create a new file.

03:47.980 --> 03:50.460
And it's going to be a class and we'll call it user.

03:51.100 --> 03:56.700
Now this particular class we're going to derive from an identity entity.

03:57.300 --> 03:59.140
So we'll use a colon.

03:59.140 --> 04:02.220
And we're going to derive from identity user.

04:03.100 --> 04:05.500
Now we're not going to add any additional properties for this.

04:05.660 --> 04:11.260
because if we do, go and take a look at the code for the identity user class, then what this gives

04:11.260 --> 04:14.260
us, it gives us an ID, which is a type of string.

04:14.260 --> 04:23.260
It uses a guide to a string, a security stamp, a username, and all of these other properties.

04:23.500 --> 04:24.740
Normalized username.

04:24.740 --> 04:25.220
Email.

04:25.220 --> 04:26.300
Normalized email.

04:26.340 --> 04:26.700
Email.

04:26.700 --> 04:27.860
Confirmed password.

04:27.860 --> 04:28.340
Hash.

04:28.820 --> 04:34.940
So we do ask the user for a password, but we store it in our database as a password hash.

04:34.940 --> 04:40.340
So even if our database does get compromised, then hashing a password is a one way operation.

04:40.700 --> 04:46.260
And I'm not saying that's impossible to crack, but it does take time and computing resources to do

04:46.260 --> 04:46.620
so.

04:47.700 --> 04:49.700
So we don't store our password in clear text.

04:49.740 --> 04:55.620
We use this approach and we're not going to tweak anything like how secure is our password hash.

04:55.940 --> 05:01.140
There is a presumption I'm making here that what we get from Microsoft doesn't need to be made secure.

05:01.660 --> 05:07.090
It is secure, and anything we change has the potential to make it less secure than it was given to

05:07.090 --> 05:07.410
us.

05:07.690 --> 05:12.370
So we've got all of this stuff just by adding or deriving from the identity user class.

05:13.250 --> 05:20.090
Next we're going to go to our store context and open up the store context class.

05:20.090 --> 05:26.490
And inside here currently we're deriving from DB context, but instead we're going to derive from the

05:26.490 --> 05:28.450
identity Dbcontext.

05:29.050 --> 05:34.130
And we're going to specify a type in here of the user entity that we have just created.

05:34.130 --> 05:39.570
So this effectively is part of the configuration that we write.

05:39.890 --> 05:42.970
That's going to give us all of our identity related tables.

05:42.970 --> 05:44.930
We don't need to do anything else inside here.

05:45.330 --> 05:47.610
Or I say we don't need to, but we are going to.

05:47.650 --> 05:50.890
If we just wanted users and nothing else, this would be sufficient.

05:51.370 --> 05:57.650
But what we'll also take the opportunity to do is we're going to create a couple of roles inside our

05:57.650 --> 06:01.250
database so that we can have an admin user.

06:01.610 --> 06:04.930
And I'm going to show a different approach to seeding data here.

06:05.450 --> 06:10.760
And we're going to use the configuration to do so, rather than creating a seed class or adding this

06:10.760 --> 06:13.360
functionality into our seed class.

06:13.640 --> 06:20.080
So if we just start typing override here, press space and start typing on, then we get access to the

06:20.120 --> 06:21.480
on model creating.

06:21.840 --> 06:22.440
And.

06:22.440 --> 06:28.360
This builder argument will make use of to add some data inside our database.

06:28.360 --> 06:29.440
So we'll use builder.

06:29.960 --> 06:31.880
And then we can specify entity.

06:31.920 --> 06:34.120
Which entity do we want to use this on.

06:34.440 --> 06:42.000
And another entity that we get with identity is the identity role which we get from Microsoft Aspnet

06:42.040 --> 06:42.800
identity.

06:43.400 --> 06:45.000
And we'll add parentheses.

06:45.000 --> 06:47.840
And below this we'll add period and has data.

06:48.560 --> 06:52.960
And we can add effectively some data into our migration.

06:53.480 --> 06:54.920
So I'll open parentheses.

06:55.400 --> 06:59.120
And inside the parentheses we'll have a new identity.

07:01.680 --> 07:02.400
Role.

07:04.280 --> 07:08.440
And we'll open curly brackets will give it a name equal to member.

07:09.960 --> 07:13.360
And we'll give it a normalized name and normalize.

07:13.360 --> 07:17.480
Names in this world are all in capitals.

07:18.840 --> 07:22.720
So remember and I'll just copy this down I'll just add a comma.

07:22.760 --> 07:23.760
Copy that down.

07:24.120 --> 07:26.080
And the next one will be admin.

07:26.800 --> 07:30.720
And the normalized name will be admin as well.

07:31.160 --> 07:33.600
And what I'll also do for this example.

07:33.600 --> 07:38.400
Now these are going to be strings of for the ID of these just like it is for the user.

07:39.560 --> 07:45.320
But if we don't specify this then Identity or entity framework will create a new ID for us.

07:45.320 --> 07:49.400
But every time we add a new migration it does something with these.

07:49.400 --> 07:57.360
So what I'll do actually is I'm just going to go out to a grid generator and just use the top link,

07:57.400 --> 08:00.480
the free online generator tool for grid generator.

08:00.880 --> 08:01.880
How many guys do I want?

08:01.880 --> 08:09.040
I want two and if I generate some guides then let's just use these as the IDs inside here.

08:09.040 --> 08:13.870
So just do the same trick that I did there just to get some goods, and it'll just make sure that these

08:13.910 --> 08:16.350
are static and not dynamic.

08:16.350 --> 08:22.390
Every time we add a new migration where our roles get removed and then replaced, and I'll do the same

08:22.390 --> 08:29.390
for the second one as well, I'll set its ID to be the other guid I generated here.

08:31.590 --> 08:37.790
And paste that in and it will just stop some weird behavior with Entity Framework when we create new

08:37.790 --> 08:42.350
migrations based on what we've done here, and just a small update based on something that's come up

08:42.350 --> 08:48.350
in a Q&amp;A from a student that's using Net ten in dotnet ten or Entity Framework ten.

08:48.390 --> 08:55.230
More specifically, then this is not enough because the ID field is dynamically generated if we don't

08:55.230 --> 08:55.750
supply it.

08:55.750 --> 08:58.350
So we do have a hard coded Guid inside there.

08:58.390 --> 08:59.030
That's a string.

08:59.030 --> 08:59.550
That's fine.

08:59.550 --> 09:04.990
But there's another property inside here also dynamically generated the concurrency stamp.

09:05.350 --> 09:08.310
And we also need to hard code this as well.

09:08.710 --> 09:18.830
So just put in a hard coded value here for both the member and the admin, so that this is no longer

09:18.830 --> 09:20.150
dynamically generated.

09:20.150 --> 09:22.310
It is a guide, but it is a string property.

09:22.310 --> 09:26.190
So we can just set member and admin inside here like this.

09:26.630 --> 09:31.470
That means it's not going to be dynamically generated if you don't have this and you're on Entity Framework

09:31.510 --> 09:38.110
Core ten, then it will definitely cause your application to throw an exception when you restart it,

09:38.110 --> 09:41.710
or when you try and start your app and apply this migration.

09:41.710 --> 09:48.190
So please ensure that you have hard coded values for any values that can be dynamically generated,

09:48.510 --> 09:50.790
such as the ID and the concurrency stamp.

09:50.790 --> 09:52.750
Prior to Net ten wasn't a big issue.

09:52.990 --> 09:56.710
It still caused you some weirdness with migrations, but it wouldn't stop your app from working.

09:56.710 --> 10:03.910
But now in Entity Framework ten, it does stop the app from working, so that will fix that issue.

10:04.310 --> 10:07.230
So that's what we need for our two different roles.

10:07.230 --> 10:13.430
And next we'll take a look at the next part of the configuration we need to set up in the program class.
