Hi All, I wanted to configure Identity in an empty ASP.NET Core web application. After going through below blogs I was able to successfully configure ASP.NET Core Identity.
Reference Links
- http://www.blinkingcaret.com/2016/11/30/asp-net-identity-core-from-scratch/
- https://wildermuth.com/2017/07/06/Program-cs-in-ASP-NET-Core-2-0
- https://codingblast.com/entityframework-core-idesigntimedbcontextfactory/
-
Install Node.js
-
Check Node.js and npm were installed
node -v npm -v
-
Install bower, yeamon and yeamon generator for asp.net
npm install -g yo bower npm install -g generator-aspnet
-
Create a project using yeamon generator and select Create an empty web application
yo aspnet
-
New project will be created based on the application name you provided in teh step 4
-
Before you open the project through visual studio, open the global.json file and update the SDK version (2.0.0). Then you should be able to open the project without any errors
-
Go to the project properties and verify whether the Target Framework is .NET Core 2.0
-
Add below NuGet Packages
Microsoft.AspNetCore 2.0.0 Microsoft.AspNetCore.Mvc 2.0.0 Microsoft.AspNetCore.StaticFiles 2.0.0
-
Open Startup.cs and add the IoC configuration required to use MVC.
-
Also, update the Configure method so that the MVC middleware is added to the pipeline with the default route. We’ve also added the StaticFiles middleware, which has to be before MVC
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseStaticFiles(); app.UseMvcWithDefaultRoute(); }
-
Adding first controller. Create Controllers folder in the root of the web project
-
Add
HomeController.cs
-
Add Views folder in the root of the web project
-
In side the Views Folder create the Shared folder
-
Add the
_Layout.cshtml
-
In the Views folder create the
_ViewStart.cshtml
file -
Add Home folder in the Views folder
-
Add
Index.cshtml
file in the Home folder -
Copy the below code into the index file
<h1>Home</h1> @if (User.Identity.IsAuthenticated) { <p>User @User.Identity.Name is signed in. <a href="/Account/Logout">Logout</a> </p> } else { <p>No user is signed in.</p> } <div> <a href="/Account/Login">Login</a> </div> <div> <a href="/Account/Register">Register</a> </div> <div> <a href="/Account/ForgotPassword">Forgot Password</a> </div>
-
Add below NuGet Packages
Microsoft.EntityFrameworkCore 2.0.0 Microsoft.AspNetCore.Identity 2.0.0 Microsoft.AspNetCore.Identity.EntityFrameworkCore 2.0.0
-
Setup application settings in the start up page
-
Add following property
public IConfiguration Configuration { get; }
-
Create the Startup constructor
public Startup(IConfiguration configuration) { Configuration = configuration; }
-
-
Modify Main Method and add using statement for
Microsoft.Extensions.Configuration;
public class Program { public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .ConfigureAppConfiguration((hostContext, config) => { // delete all default configuration providers config.Sources.Clear(); config.AddJsonFile("appsettings.json", optional: true); }) .Build(); host.Run(); } }
-
Add
appsettings.json
file into the web project folder{ "ConnectionStrings": { "AuthDbConnection": "Data Source=.;Initial Catalog=AuthDb;Integrated Security=True" } }
-
Add new folder called CustomIdentity. Maintain your custom DbContext of the identity database. Add below implementations as two classes in the that folder
-
ApplicationDbContext
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace ASRIdentity.Web.CustomIdentity { public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // Customize the ASP.NET Identity model and override the defaults if needed. // For example, you can rename the ASP.NET Identity table names and more. // Add your customizations after calling base.OnModelCreating(builder); } } }
-
ApplicationUser
using Microsoft.AspNetCore.Identity; namespace ASRIdentity.Web.CustomIdentity { // Add profile data for application users by adding properties to the ApplicationUser class public class ApplicationUser : IdentityUser { } }
-
-
In order to add mirgrations you need to implement
IDesignTimeDbContextFactory
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using System.IO; namespace ASRIdentity.Web.CustomIdentity { public class ApplicationDesignTimeDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext> { public ApplicationDbContext CreateDbContext(string[] args) { IConfigurationRoot configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var builder = new DbContextOptionsBuilder<ApplicationDbContext>(); var connectionString = configuration.GetConnectionString("AuthDbConnection"); builder.UseSqlServer(connectionString); return new ApplicationDbContext(builder.Options); } } }
-
Add below code peice in the
Startup.cs
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("AuthDbConnection"))); services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders();
-
Add below code peice in the
Startup.cs
app.UseAuthentication();
-
Add the following NugetPackage. Due VS issue do not import the NuGet Packages using package manager tool. Unload the project add the below items to project file.
<ItemGroup> <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" /> </ItemGroup>
-
Build the solution
-
In the CMD cd into the project root and add migrations and update the database
dotnet ef migrations add Initial dotnet ef database update
-
Update AccountController
public class AccountController : Controller { private readonly UserManager<ApplicationUser> _userManager; private readonly SignInManager<ApplicationUser> _signInManager; public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager) { this._userManager = userManager; this._signInManager = signInManager; }
-
Add Registry GET and POST methods
public IActionResult Register() { return View(); } [HttpPost] public async Task<IActionResult> Register(string email, string password, string repassword) { if (password != repassword) { ModelState.AddModelError(string.Empty, "Password don't match"); return View(); } var newUser = new ApplicationUser { UserName = email, Email = email }; var userCreationResult = await _userManager.CreateAsync(newUser, password); if (!userCreationResult.Succeeded) { foreach (var error in userCreationResult.Errors) { ModelState.AddModelError(string.Empty, error.Description); } return View(); } var emailConfirmationToken = await _userManager.GenerateEmailConfirmationTokenAsync(newUser); var tokenVerificationUrl = Url.Action("VerifyEmail", "Account", new { id = newUser.Id, token = emailConfirmationToken }, Request.Scheme); ////await _messageService.Send(email, "Verify your email", $"Click <a href=\"{tokenVerificationUrl}\">here</a> to verify your email"); return this.Redirect("/"); }
-
And now the razor file in
Views/Account/Register.cshtml
@{ ViewData["Title"] = "Register"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Register</h2> <form method="POST"> <div> <label>Email</label> <input type="email" name="email" /> </div> <div> <label>Password</label> <input type="password" name="password" /> </div> <div> <label>Retype password</label> <input type="password" name="repassword" /> </div> <input type="submit" /> </form> <div asp-validation-summary="All"></div>
-
Run the application and try to add a user
-
Check the added user in the database
SELECT * FROM [AuthDb].[dbo].[AspNetUsers]
-
Add Login functionality in AccountController
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(string email, string password, bool rememberMe)
{
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
ModelState.AddModelError(string.Empty, "Invalid login");
return View();
}
if (!user.EmailConfirmed)
{
ModelState.AddModelError(string.Empty, "Confirm your email first");
return View();
}
var passwordSignInResult = await _signInManager.PasswordSignInAsync(user, password, isPersistent: rememberMe, lockoutOnFailure: false);
if (!passwordSignInResult.Succeeded)
{
ModelState.AddModelError(string.Empty, "Invalid login");
return View();
}
return Redirect("~/");
}
- Add login razor view
@{
ViewData["Title"] = "Login";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Login</h2>
<form method="POST">
<div>
<label>Email</label>
<input type="email" name="email" />
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
</div>
<input type="submit" />
</form>
<div asp-validation-summary="All"></div>
Posted by Ashanka Randeniya
Twitter: @AshankaSR