Overview Of Identity In ASP.NET Core 2.0

Introduction
 
It is membership system that allows us to add login functionality to our application. A user may create account and log in using credentials or can use external login providers, such as Google, Microsoft Account, Twitter, Facebook etc.
 
We can configure ASP.NET Core Identity to use SQL Server database to store the user profile data or we can use our own persistent store, such as Azure Table Storage.
 
We can either create an application using Visual Studio or .NET Core CLI.
 
In VS, select File => New => Project, select ASP.NET Core Web Application from the popup.
 
After that, select Web Application (Model-View-Controller) for framework 2.x with Individual User Account as an authentication mode.
 
 
 
Using .NET Core CLI, we can create a new project using "donet new mvc --auth Individual" command. This will create a new project with the same template as mentioned above, using Visual Studio.
 
Command
  1. > donet new mvc --auth Individual  
Configure Identity Services
 
The ConfigureServices method of startup class contains configuration for the Identity Services. The "services.AddIdentity" method adds the default identity system configuration for specific user and role. These services are available to the application using DI (dependency injection).
  1. public void ConfigureServices(IServiceCollection services)  
  2. {  
  3.     services.AddDbContext<ApplicationDbContext>(options =>  
  4.         options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));  
  5.   
  6.     services.AddIdentity<ApplicationUser, IdentityRole>()  
  7.         .AddEntityFrameworkStores<ApplicationDbContext>()  
  8.         .AddDefaultTokenProviders();  
  9.   
  10.   
  11. …  
  12. …  
  13. …  
  14. }  
Identity Services are enabled for the application by calling "UseAuthentication" method on the Configure method of startup class. This method adds authentication middleware to the request pipeline.
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
  2. {  
  3. …  
  4. …  
  5. app.UseAuthentication();  
  6.   
  7. app.UseMvc(routes =>  
  8. {  
  9.     routes.MapRoute(  
  10.         name: "default",  
  11.         template: "{controller=Home}/{action=Index}/{id?}");  
  12. });  
  13. }  
The template creates classes to represent role, user, and database context that, from the framework classes, inherits IdentityRole, IdentityUser, and IdentityDbContext.
  1. public class ApplicationUser : IdentityUser
  2. {  
  3. }  
  4.   
  5. public class ApplicationDbContext : IdentityDbContext<ApplicationUser>  
  6. {  
  7.         public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)  
  8.             : base(options)  
  9.         {  
  10.         }  
  11.   
  12.         protected override void OnModelCreating(ModelBuilder builder)  
  13.         {  
  14.             base.OnModelCreating(builder);  
  15.         }  
  16. }  
  17. public class AppIdentityRole : IdentityRole  
  18. {  
  19. }  
 This template also added a default connection string to the appsetting.json file. In this connection string, the default database name is "aspnet-{project name}-{guid}". For demonstration, I have changed it to "IdentityTest".
 
 
 
 appsettings.json
  1. {  
  2.   "ConnectionStrings": {  
  3.     "DefaultConnection""Server=(localdb)\\mssqllocaldb;Database=IdentityTest;Trusted_Connection=True;MultipleActiveResultSets=true"  
  4.   },  
  5.   "Logging": {  
  6.     "IncludeScopes"false,  
  7.     "LogLevel": {  
  8.       "Default""Warning"  
  9.     }  
  10.   }  
  11. }  
Now, I am launching the application and clicking the Register link. It will display the following page. Insert the required information and click on Register button. If this is the first time, your system will ask for database migrations.
 
 
 
 
 
By clicking on "Apply Migrations", you can migrate the database. Alternatively, we can also use command line to perform the migration. Just, use the following command.
  1. > dotnet ef database update  
The migration will generate identity-related tables into the database.
 
 
 
We can also test ASP.NET Core Identity with our application without a persistent database by using an in-memory database. To use an in-memory database, we need to add Microsoft.EntityFrameworkCore.InMemory package to our application and modify "AddDbContext" call with the following code in ConfigureServices method of Startup class.
  1. services.AddDbContext<ApplicationDbContext>(options =>  
  2.                     options.UseInMemoryDatabase(Guid.NewGuid().ToString()));  
The "Register" action of AccountController is invoked when user click on "Register" link. This action method create user by calling "CreateAsync" method of UserManager class. The UserManager class provided to the controller class by using dependency injection.
  1. public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)  
  2. {  
  3.     ViewData["ReturnUrl"] = returnUrl;  
  4.     if (ModelState.IsValid)  
  5.     {  
  6.         var user = new ApplicationUser { UserName = model.Email, Email = model.Email };  
  7.         var result = await _userManager.CreateAsync(user, model.Password);  
  8.         if (result.Succeeded)  
  9.         {  
  10.             _logger.LogInformation("User created a new account with password.");  
  11.   
  12.             await _signInManager.SignInAsync(user, isPersistent: false);  
  13.             _logger.LogInformation("User created a new account with password.");  
  14.             return RedirectToLocal(returnUrl);  
  15.         }  
  16.         AddErrors(result);  
  17.     }  
  18.   
  19.     // If we got this far, something failed, redisplay form  
  20.     return View(model);  
  21. }  
SignIn and SignOut
 
The ASP.net core Identity provides a class called "SignInManager" that is used to authenticate the user and sign-in (login) or sign-out user. This "SignInManager" class provided to the controller by using dependency injection.
 
The "SignInManager" class has various methods for Sign In, such as PasswordSignInAsync, SignInAsync etc. It also contains the method for external login, such as ExternalLoginSignInAsync. This class contains the method "SignOutAsync" for signing out the user from system. Apart from that, this class has methods for checking user lock status, reset lock, lock user, refresh token etc.
  1. //For Sign in  
  2. await _signInManager.SignInAsync(user, isPersistent: false);  
  3. //For sign out  
  4. await _signInManager.SignOutAsync();  
Override default Configuration
 
We can also override the default behavior of the Identity class. There is no configuration required if we want to use default configuration. The configuration for Identity can be change by defining IdentityOption in ConfigureServices method of startup class.
  1. public void ConfigureServices(IServiceCollection services)  
  2. {  
  3.     services.AddDbContext<ApplicationDbContext>(options =>  
  4.         options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));  
  5.   
  6.     //services.AddDbContext<ApplicationDbContext>(options =>  
  7.     //        options.UseInMemoryDatabase(Guid.NewGuid().ToString()));  
  8.   
  9.     services.AddIdentity<ApplicationUser, IdentityRole>()  
  10.         .AddEntityFrameworkStores<ApplicationDbContext>()  
  11.         .AddDefaultTokenProviders();  
  12.   
  13.     //Overide the configuration  
  14.     services.Configure<IdentityOptions>(options =>  
  15.     {  
  16.         // Password settings  
  17.         options.Password.RequireDigit = true;  
  18.         options.Password.RequiredLength = 8;  
  19.         options.Password.RequireNonAlphanumeric = false;  
  20.         options.Password.RequireUppercase = true;  
  21.         options.Password.RequireLowercase = false;  
  22.   
  23.         // Lockout settings  
  24.         options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(60);  
  25.         options.Lockout.MaxFailedAccessAttempts = 10;  
  26.         options.Lockout.AllowedForNewUsers = true;  
  27.   
  28.         // User settings  
  29.         options.User.RequireUniqueEmail = true;  
  30.     });  
  31.   
  32.     services.ConfigureApplicationCookie(options =>  
  33.     {  
  34.         // Cookie settings  
  35.         options.Cookie.HttpOnly = true;  
  36.         options.Cookie.Expiration = TimeSpan.FromDays(150);  
  37.         options.LoginPath = "/Account/Login";   
  38.         options.LogoutPath = "/Account/Logout";   
  39.         options.AccessDeniedPath = "/Account/AccessDenied";   
  40.         options.SlidingExpiration = true;  
  41.     });  
  42.   
  43.     // Add application services.  
  44.     services.AddTransient<IEmailSender, EmailSender>();  
  45.   
  46.     services.AddMvc();  
  47. }  
Summary
 
We can add Identity in ASP.NET Core using very a few lines of simple code that add registration, login, logout, forgot, and reset password features to our application. ASP.NET Core Identity will take care of everything, such as password hashes, validating tokens, finding users, inserting users, etc.