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 DbSet
s 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!