GitHub Repository
All the code in this series can be found at https://github.com/dombarter/Solar.API
The Motivation
There are a lot of tutorials out there for how to scaffold .NET Identity into your project, but that comes along with full register/login Razor pages. The idea of this post is to take the core .NET Identity logic to setup the database tables and provide key wrappers - but manage login and registering using our own API endpoints.
NuGet Packages
You need to start by adding the following NuGet packages to your project:
- Microsoft.AspNetCore.Identity.EntityFrameworkCore
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
Database Connection
You now need to get the connection to your SQL server. Add it into your appsettings.json file like so:
{
"ConnectionStrings": {
"Default": "Data Source=localhost\\SQLEXPRESS...."
}
}
DbContext Class
Instead of making a standard DbContext class we need to extend the IdentityDbContext class which will provide us with a number of extra DbSets including user and role information. Here is a basic example:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Solar.Data
{
public class SolarDbContext : IdentityDbContext<IdentityUser>
{
public SolarDbContext(DbContextOptions options) : base (options)
{
}
}
}
Configure Entity Framework & Identity
Now we need to configure Entity Framework, so it can connect the database and the DbContext, as well as configure Identity with key options such as password requirements.
Add the following lines to your startup class, Program.cs:
// Add the database connection
builder.Services.AddDbContext<SolarDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
// Setup identity
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequiredLength = 8;
}).AddEntityFrameworkStores<SolarDbContext>();
Database Migration
With everything setup, we can now add an initial migration and apply this migration to our database:
add-migration init
update-database
You will now notice 5 or 6 tables have been created to store all the user and role information etc.
Using .NET Identity
We can now login and register using the UserManager and SignInManager like below:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Solar.DTOs.Inbound;
namespace Solar.API.Controllers
{
[ApiController]
[Route("user")]
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
[HttpPost]
[Route("register")]
public async Task<IActionResult> Register([FromBody] RegisterDto model)
{
var user = new IdentityUser
{
UserName = model.Email,
Email = model.Email
};
// Create the user
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return Ok();
}
return new BadRequestObjectResult(result.Errors);
}
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginDto model)
{
// Login
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false);
if (result.Succeeded)
{
return Ok();
}
return BadRequest("Incorrect email or password");
}
}
}
And that’s it - you can now create users, and login, all using .NET Identity and managing all the DTOs and endpoint logic yourself!