WEBVTT

00:00.000 --> 00:05.190
Okay, now that we've set up our store context and we've got our user entity, let's head over to the

00:05.190 --> 00:12.480
program class to continue configuring this and we'll open up the Program.cs.

00:12.720 --> 00:14.100
So pretty straightforward to do.

00:14.130 --> 00:20.640
We just need to add a service which is going to provide us with the identity API endpoints.

00:20.640 --> 00:25.620
Those ones I was mentioning in the previous lesson that gives us things like the login, the register

00:25.620 --> 00:32.190
and so on, and configure the Entity Framework stores, which is responsible for creating the identity

00:32.220 --> 00:34.230
tables in our database.

00:34.230 --> 00:37.020
So to do this we'll use builder dot services.

00:37.020 --> 00:41.550
And we can use Add identity API endpoints.

00:42.030 --> 00:47.910
And we pass in here as a type parameter the user that we created from API entities.

00:47.910 --> 00:49.920
And then we give it some options.

00:49.950 --> 00:55.050
And we'll open an arrow and then curly brackets so we can put an expression in here.

00:55.230 --> 01:02.700
Now what we could do here is we've got options that we can configure various aspects of identity.

01:02.730 --> 01:07.470
Things like the password complexity and things related to the user.

01:07.470 --> 01:13.200
I'll just do one of these and let's say, for example, we don't want users to sign up under different

01:13.200 --> 01:16.410
usernames that have different email addresses.

01:16.410 --> 01:20.760
So we might specify that we want them to require a unique email.

01:20.790 --> 01:24.870
Another thing that we might want to do is take a look at the password options.

01:24.870 --> 01:31.410
And all of these different options require digit required length, require unique characters, require

01:31.410 --> 01:34.650
lowercase, non-alphanumeric, and uppercase.

01:34.650 --> 01:42.420
What this means is that by default, identity ASP.Net identity requires unique passwords, and the default

01:42.420 --> 01:44.430
values for these is.

01:44.430 --> 01:46.950
It has to be at least six characters in length.

01:46.980 --> 01:49.650
It requires a digit or a number.

01:49.650 --> 01:52.050
It requires unique characters.

01:53.280 --> 02:00.960
So we can't just have a, a, a a, a as a password, and it requires a lowercase character and it requires

02:00.960 --> 02:06.660
non-alphanumeric a special character as well as well as an uppercase character.

02:06.660 --> 02:13.000
So in order to register a user with identity, then we have to meet the password complexity requirements.

02:13.000 --> 02:14.410
I'm going to say that's fine.

02:14.410 --> 02:19.810
I want complex passwords and I'll leave that as it is below the parentheses.

02:19.810 --> 02:20.890
The closing parentheses.

02:20.890 --> 02:23.680
We just need to add a few more bits of configuration.

02:23.680 --> 02:24.730
We'll add roles.

02:24.730 --> 02:28.090
We'll add them now, but we're not going to use them for quite some time.

02:28.090 --> 02:36.460
And for the roles we'll just use the identity role entity that we get from ASP.Net identity.

02:36.490 --> 02:43.900
Add the parentheses and we add one more bit of configuration to add identity framework stores.

02:44.110 --> 02:47.500
And we pass this the store context.

02:47.710 --> 02:53.620
And you'll see this when we create a migration, it's going to create us a bunch of tables related to

02:53.650 --> 02:54.790
identity.

02:54.790 --> 03:02.470
So below that in the HTTP request pipeline section our middleware we also need to enable middleware

03:02.470 --> 03:04.030
for this as well.

03:04.540 --> 03:10.450
Now above the controllers and ordering is especially important here as well.

03:10.480 --> 03:15.010
So the first bit of middleware we add is App.use authentication.

03:15.760 --> 03:23.410
And we use authentication so that our app knows who the user is by validating their identity.

03:23.440 --> 03:27.460
So is it the user Bob that's authenticating or is it the admin.

03:27.460 --> 03:31.420
And then below this we'll use the app use authorization.

03:32.050 --> 03:37.000
And this is our application's way of defining what that user is allowed to do.

03:37.030 --> 03:42.880
Is Bob allowed to access this area or is the admin allowed to access this area.

03:42.880 --> 03:45.130
So we need both of those bits of middleware here.

03:45.130 --> 03:52.180
And then another bit of middleware we need to add is for our API endpoints for identity.

03:52.180 --> 03:58.750
And the way that we specify this is we'll say app map group and we'll say API.

03:59.230 --> 04:03.850
And then add a period and then map identity API.

04:03.850 --> 04:08.050
And once again we pass this our user entity here.

04:08.830 --> 04:14.700
So this map group just means that when we use these we're going to need to specify API as part of the

04:14.700 --> 04:15.720
URL.

04:15.720 --> 04:20.250
So it's going to be API forward slash login for example.

04:20.250 --> 04:28.620
And then the map identity API gives us effectively all of the endpoints I was highlighting here, which

04:28.620 --> 04:31.170
is all of these.

04:31.200 --> 04:34.980
So just by adding that we have access to all of that functionality.

04:34.980 --> 04:42.780
So we'll also go back to our seed class as well because we'll create a couple of users inside our application.

04:42.780 --> 04:45.900
So we'll open up the DB initializer class.

04:45.900 --> 04:49.350
And we're actually going to add something else to this as well.

04:49.350 --> 04:56.520
So as well as the store context we're going to need our user manager which we get from ASP.Net identity.

04:56.520 --> 05:00.690
So as a second argument here I'll specify user manager.

05:00.780 --> 05:06.900
And again we use our user entity that we've created for this and we'll call it user manager.

05:06.930 --> 05:14.730
And after the database migrates let's check first of all to see if we have any users in our database.

05:14.730 --> 05:18.690
And if we do not then we will seed a couple of users in.

05:18.690 --> 05:20.640
So we use the Not operator.

05:20.730 --> 05:24.840
We'll use our user manager and this gives us access to our users.

05:24.840 --> 05:29.430
In fact it gives us access pretty much to our store context at this point.

05:29.430 --> 05:32.730
But specifically here we're going to access the users.

05:32.910 --> 05:37.230
But the user manager gives us extra functionality than the store context.

05:37.230 --> 05:42.960
It's like having access to our store context and all of our user functionality at the same time.

05:43.020 --> 05:48.030
So we'll check to see if we have any users in our database, and we'll use the any to check that.

05:48.030 --> 05:52.080
So if there are no users then we're going to seed some users in.

05:52.080 --> 05:59.130
So I'll create a new user and say if our user equals new user and we'll give it a username and we have

05:59.130 --> 06:04.470
access to that property for the user and the username, in this case I'm going to specify.

06:04.530 --> 06:09.330
And even though it's username I'm actually going to specify an email address here.

06:09.330 --> 06:12.180
And I'll explain why soon when it comes to logging in.

06:12.180 --> 06:17.580
And we'll also have an email which I am going to set to exactly the same thing.

06:17.580 --> 06:22.760
Looks a bit weird this, but there is a reason I've specified username as Bob at test.com and not just

06:22.760 --> 06:26.090
Bob, and I'll explain why that is soon.

06:26.120 --> 06:28.730
For now we're just going to get things configured.

06:28.730 --> 06:34.010
So below the var user let's use our user manager to create the user.

06:34.040 --> 06:40.790
So I'm going to use await as this makes an or execute something against our database say await user

06:40.790 --> 06:41.450
Manager.

06:41.450 --> 06:45.140
And I'm going to use the create async method to create a user.

06:45.200 --> 06:51.200
And if we take a look at the options for this, the second overload I've just come down to in the documentation,

06:51.230 --> 06:54.350
this takes the user object which we've created up here.

06:54.350 --> 07:00.590
And it also can take a password that we can supply so that when we create this user it has a password

07:00.590 --> 07:01.490
we can use.

07:01.490 --> 07:05.900
So I'll pass in the user and then create a complex password.

07:05.900 --> 07:09.080
And please bear in mind this does need to be complex.

07:09.080 --> 07:15.140
So I'm going to use capital P a dollar dollar W0RD.

07:15.770 --> 07:17.750
And just a word of warning here.

07:17.750 --> 07:25.310
If you do use a non complex password then this will fail when it comes to starting our application and

07:25.310 --> 07:31.640
attempting to seed our data, and it's going to pretty much fail silently as well at this stage, unless

07:31.640 --> 07:35.360
we increase the logging level of what's going on when we do this.

07:35.360 --> 07:38.510
So please do make sure you've got a complex password here.

07:39.020 --> 07:44.270
Otherwise your users will not be seeded into the database and it won't give you any good information

07:44.270 --> 07:45.830
about why it went wrong.

07:45.860 --> 07:53.630
I'm also going to take the opportunity to use the user manager to add to role async for this user.

07:53.630 --> 07:59.120
So I'll specify user and I'm going to specify member as the name of the role.

07:59.150 --> 08:00.380
Once again this is a string.

08:00.380 --> 08:05.000
Please make sure it matches one of the roles that you've created in the store context.

08:05.930 --> 08:13.460
And I'll just copy this code and paste it below, because we'll also have an admin user as well.

08:13.460 --> 08:17.090
We'll create it at the same time, although we're not going to use it for quite some time.

08:17.090 --> 08:22.520
So I'm just going to change Bob to admin and admin there as well.

08:22.550 --> 08:26.060
Keep the password, but I'm going to add the admin to two roles.

08:26.090 --> 08:35.300
So instead of add to roll async, I'm going to use the version of this that takes an array of roles.

08:35.300 --> 08:42.290
So I'm going to wrap the member in square brackets, add a comma, and also specify admin.

08:42.440 --> 08:48.320
And I've got an error inside here because I need to add the user manager to this as well.

08:48.320 --> 08:52.880
Which means we need to get our user manager as well inside this method.

08:52.880 --> 08:59.630
So I'm just going to copy this line for var context and paste this below.

08:59.780 --> 09:02.780
And I'm going to call this user manager.

09:03.320 --> 09:07.430
And I'm going to get hold of the user manager.

09:07.430 --> 09:11.480
And once again we specify the user entity inside there.

09:11.570 --> 09:16.670
And instead of saying fail to retrieve store context I'm going to say user manager.

09:16.850 --> 09:21.920
And then as a second parameter to our seed data I'm just going to pass in the user manager.

09:22.040 --> 09:23.060
So that's the setup.

09:23.060 --> 09:29.360
And in the next lesson we'll take a look at creating a new migration and checking out what this gives

09:29.360 --> 09:30.020
us.
