What is ASP.NET Core Identity?
This is part 65 of ASP.NET Core tutorial. In this video and in our upcoming videos in the series, we'll discuss everything you need to know to effectively use ASP.NET Core Identity to implement security related features in your ASP.NET Core application.
What is ASP.NET Core Identity? Well, it's a built-in membership system. It allows us to create, read, update, and delete user accounts, account confirmation, authentication and authorization, password recovery, two-factor authentication with SMS. It also supports external login providers like Microsoft, Facebook, Google, etc., and much more. We'll discuss implementing these features in our upcoming videos in the series.
Step 1: Inherit from IdentityDbContext
Now let's add support for ASP.NET Core Identity in our ASP.NET Core application. The first step is to make our application DB context class inherit from IdentityDbContext instead of DbContext. Let's bring in the required namespace by pressing control period. Notice this class is present in Microsoft an ASP.NET Core Identity and Entity Framework Core namespace.
If you're wondering why do we need to inherit from IdentityDbContext class, well that's because this class provides all the DB set properties needed to manage the identity tables in the underlying data store, in our case Microsoft SQL Server database. We'll see all the tables that the ASP.NET Core Identity Framework generates in just a minute.
For now, let's go to the definition of this IdentityDbContext class. Notice it inherits from IdentityDbContext<IdentityUser, IdentityRole>. If we go to the definition of this class, it inherits from another variation of IdentityDbContext class. As we go through the inheritance chain, we'll see ultimately IdentityDbContext class inherits from DbContext class. There we go. This variation of IdentityUserContext class inherits from the DbContext class. This is the reason if our ApplicationDbContext class is inheriting from DbContext class, we don't have to explicitly again inherit from the DbContext class. So this is our first step, make your ApplicationDbContext class derive from the IdentityDbContext class.
Next, we need to add ASP.NET Core Identity services to our application. Like many things in ASP.NET Core, we do this in the ConfigureServices method of the startup class, which is present in this Startup.cs file. To add identity services on this IServiceCollection interface, we call the aptly named AddIdentity method.
Notice from the IntelliSense, this method has got two generic parameters, TUser and TRole, where TUser is a class and TRole is also a class. So for the first parameter I'm going to pass the built-in IdentityUser class as the argument, and for the second parameter, I'm going to pass IdentityRole. Bringing in the required namespace for these two classes, which is Microsoft.AspNetCore.Identity.
If you're wondering why we're using this IdentityUser class, well to understand that, first let's go to the definition of this class. It inherits from IdentityUser<string>, so let's go to the definition of this class as well. Notice we have properties like Email, PasswordHash, UserName, etc. ASP.NET Core Identity uses this built-in IdentityUser class to manage the details of the registered users of our application. For every property that you see in this class, we have a corresponding column in the underlying users table. We'll look at that in action in just a bit.
But if you take a look at this class, this class has got only a limited set of properties. What if you want to store additional information, like the gender of the user and their City? We don't have properties for gender and city within this built-in IdentityUser class. So what we can do is create a custom class and make that custom class inherit from this IdentityUser class, and within that custom class, we'll include properties for all the additional data that we want to capture. And then plug that custom class in instead of the built-in IdentityUser class. We'll discuss how to do this in our upcoming videos in this series.
Similarly, IdentityRole is also a built-in class provided by ASP.NET Core Identity system and as the name implies, it is used to manage user role information. We'll discuss adding new roles and implementing role-based authorization in our upcoming videos.
Now, we want to use Entity Framework Core to retrieve user and role information from the underlying SQL server database. Using Entity Framework Core, we configure that by calling AddEntityFrameworkStores method. As a generic argument, we specify our application DB context, which is AppDbContext. This is our second step.
Step 3: Add Authentication Middleware
Adding ASP.NET Core Identity services. Next, add the authentication middleware to our application's request processing pipeline. Remember, it is the Configure method in the startup class that configures our application's request processing pipeline. So in the Configure method to add authentication middleware, call UseAuthentication method. So in our Startup.cs file, in the Configure method, let's call UseAuthentication extension method.
We want to be able to authenticate users before the request reaches the MVC middleware, so it's important we add the authentication middleware before the MVC middleware.
Step 4: Create a Database Migration
Next, we need to create ASP.NET Core Identity tables in the underlying SQL Server database. For that, we need to create a new migration. Before that, let's build our solution to make sure we do not have any compilation errors. There we go, build succeeded.
Next, we want to add a new migration. To add a new migration, we use add-migration command. We discussed migrations in detail in our previous videos in the series. So within Visual Studio in the Package Manager Console window, let's use add-migration command and we need to specify a name. Let's call the migration 'AddingIdentity' and then press the Enter key. We have an error: The entity type IdentityUserLogin<string> requires a primary key to be defined.
If you are getting this error, the most likely cause is within your ApplicationDbContext class, you are overriding OnModelCreating method but you are not calling the base class OnModelCreating method. In this case, the base class is IdentityDbContext. To fix this error, all we need to do is call the base class OnModelCreating method using the base keyword. And then to this, pass this incoming ModelBuilder object. The keys of Identity tables are mapped in OnModelCreating method of this IdentityDbContext class. By calling base.OnModelCreating, we are calling the OnModelCreating method of this IdentityDbContext class so that keys are mapped and we no longer should have this error when we add the migration.
So let's try the migration command once again. Migration added. Notice the code in this migration creates several identity tables like AspNetRoles, AspNetUsers, etc. Before we apply this migration to our database let's take a look at the tables that we have in the EmployeeDB database. At the moment, we only have two tables: Employees and __EFMigrationsHistory.
Apply Migration and Review Schema
Now let's update our database with this migration. For that we use update-database command. If we take a look at our EmployeeDB database now, notice we have several identity tables. If we take a look at this AspNetUsers table, notice the columns in this table correspond to the properties that we have in this built-in class IdentityUser. ASP.NET Core uses this built-in class IdentityUser and Entity Framework Core to manage the data that we have in this AspNetUsers table. And this is exactly the reason why we have specified IdentityUser as the generic argument for AddIdentity method right here. And the same is true even for IdentityRole.
At the moment in this AspNetUsers table, we do not have columns to store additional information about the users like their gender or city. In our upcoming videos in the series, we'll discuss how to extend this built-in IdentityUser class so we could store additional information about our registered users.
Conclusion and Next Steps
At this point, our application is configured to use ASP.NET Core Identity. We also created the required Identity tables in the underlying SQL Server database. Our next step is to register new users. We'll discuss how to do that using ASP.NET Core Identity in our next video. That's it in this video. Thank you for listening.