A few interfaces need to be implemented:
IUserStore<TUserType>
IRoleStore<TRoleType>
TUserType and TRoleType are custom classes that represent a user or a role. There are other interfaces that can be implemented which also implement one of the interfaces above. For example IUserRoleStore
or IUserPasswordStore
which both also implement IUserStore
. Use them in combination to obtain more customization, for example if you want to override how roles get stored against the user.
Once those are implemented, you need to enable identity and also set the user and role store implementations:
services // IServiceCollection
.AddIdentity<UserData, RoleData>(options =>
{
options.SignIn.RequireConfirmedEmail = false;
options.SignIn.RequireConfirmedPhoneNumber = false;
})
Notice that you can modify validation features as options.
There are built-in managers for using these implementations of IUserStore and IRoleStore, but if you're using a custom type (vs. using the default IdentityUser
/ IdentityRole
) then you need to let the IoC container know:
services
.AddIdentity<UserData, RoleData>(options =>
{
options.SignIn.RequireConfirmedEmail = false;
options.SignIn.RequireConfirmedPhoneNumber = false;
})
.AddUserManager<UserManager<UserData>>()
.AddRoleManager<RoleManager<RoleData>>()
.AddSignInManager<SignInManager<UserData>>()
.AddUserStore<UserStore>()
.AddRoleStore<RoleStore>()
.AddDefaultTokenProviders();
I don't know why you have to specify the stores as well, seeing as they're defined in AddIdentity()
...
Now that those are defined, the managers have been added to DI and they can now be requested as services. So here is an example of creating a new user, using the managers:
public UsersController(UserManager<UserData> userManager)
{
_userManager = userManager;
}
[HttpPost, Route("")]
public async Task<IActionResult> RegisterUser([FromBody] UserInfo payload)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
var user = new UserData
{
FirstName = payload.FirstName,
LastName = payload.LastName,
Username = payload.Username,
Email = payload.Email,
Password = payload.Password,
NormalizedUserName = payload.Username,
NormalizedEmail = payload.Email,
UserId = Xid.NewXid().ToString()
};
var result = await _userManager
.CreateAsync(user, payload.Password)
.ConfigureAwait(false);
if (!result.Succeeded)
{
foreach(var error in result.Errors)
ModelState.AddModelError(error.Code, error.Description);
return StatusCode(500, ModelState);
}
return Created($"/users/{user.UserId}", user);
}