Authentication with Identity Db And Entity Framework In DotNet

Server Tombak
nacressoftware
Published in
5 min readJun 18, 2024

Hello Everyone, I hope you are all doing well and in good health!
Today we will dive in and learn how to entegrate Identity in .Net to easily handle Authentication and role management. We will be going on step step to write clear and understandable Article about how it may help us and how we can entegrate it to our projects.

Identity library makes easier to manage Authentication operations like Register, Login, updating user informations, role management etc.

Needed Nuget Packages

  1. Microsoft.AspNetCore.Identity.EntityFrameworkCore
  2. Microsoft.EntityFrameworkCore
  3. Microsoft.EntityFrameworkCore.Design
  4. Microsoft.EntityFrameworkCore.SqlServer
  5. Microsoft.EntityFrameworkCore.Tools

Since we are using Entity Framework core we need to add these packages to complete the configuration easily.

Let’s Start to coding!!

First step is to create our user class.

 public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.Now;

}

I just added these 3 property because It’s implementing IdentityUser and Identity user alread have properties that we may need by default. Like UserName, email, passwordhash.

Data Layer

I have created a class and called it as ApplicationDbContext, I implemented IdentityDbContext because we are using Identity library and it will add needed tables for us. So it’s one of the perfect advantages of Identity.

public class ApplicationDbContext : IdentityDbContext<AppUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}

public DbSet<AppUser> ApplicationUsers { get; set; }

}

Now let’s update database and see what we have in the latest situation but before we do that we should complete the configuration on program.cs

builder.Services.AddDbContext<ApplicationDbContext>(
context => context.UseSqlServer(builder.Configuration["DefaultConnection"])
);

builder.Services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();

Now we can go on but get sure that you have written connection string in Appsetting.json with the name of “DefaultConnection” like that:

  "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Identity;Integrated Security=True;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False"

Update Database

Write these two commands with turn in Package Manager Console

add-migration Initialize
Update-database

After writing and running these commands check your database if you are not seeing below tables then there should be a problem check error if there is any then you should fix them otherwise it will not work successfully.

DBTables

Now our database configuration completed successfully and we can go on to write our functions like Register, Login, Logout and etc.

Coding Controller Layer

I have created a controller and called it as AccountController

{
[ApiController]
[Route("Api/[Controller]")]
public class AuthController : ControllerBase
{
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
public AuthController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}

[HttpPost]
public async Task<IActionResult> Register(AppUser user,string password)
{
var result = await _userManager.CreateAsync(user, password);
if(!result.Succeeded)
{
return BadRequest(result.Errors);
}

return Ok(result.Succeeded);
}

}

For register operation we used UserManager’s CreateAsync method. It’s taking the User and password as parameters. When we call that endpoint It will create a new user for us in AspNetUsers table.

Testing Register Operation

We can test that by running the app. I have created the project as API project so I will be making tests with swagger its coming by default. If you created the project as API too you just need to run it swagger will be already added for API tests.

testing Register Operation

If you click the execute button it will give you the result of true which means that user added successfully.

Adding Login Endpoint

That Login Operation will be added to the AccountController class like Register Operation.

[HttpPost("login")]
public async Task<IActionResult> Login(string username, string password)
{
var result = await _signInManager.PasswordSignInAsync(username, password, true, false);
if(!result.Succeeded)
{
return BadRequest(result.Succeeded);
}
return Ok(result.Succeeded);
}

here we are sending a request by SignInManager and checking if the the username that we send is belong to a user and the password match. If it is then we are returning true which is coming from result. Succeeded if the password or username does not match then result.Succeeded is returning false.

We could do that operation by email too, if you want to do it by email then you can update login fuction like below;

[HttpPost("login")]
public async Task<IActionResult> Login(string email, string password)
{
var user = await _userManager.FindByEmailAsync(email);

var result = await _signInManager.PasswordSignInAsync(user, password, true, false);

if(!result.Succeeded)
{
return BadRequest(result.Succeeded);
}
return Ok(result.Succeeded);
}

It’s up to you, both of them will be working successfully.

Testing Login Operation

As you can see from the below picture that it signed in successfully.

Testing Login Operation

Normally I was just planning the integration, Login and Register part but I guess that will be so limited So let’s go on and see how we can add new Role to the project and Logout part.

Logout Operation

For logout we can just need to call SignOutAsync from SignInManager class like that.


[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return Ok();
}

Adding Role

For Adding role operation I updated the AccountController constructor and Injected RoleManager in AccountController:

Updated AccountController constructure code:

private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AuthController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_signInManager = signInManager;
_roleManager = roleManager;
}

And I updated Register endpoint too

   [HttpPost]
public async Task<IActionResult> Register(AppUser user,string password)
{
var result = await _userManager.CreateAsync(user, password);
if(!result.Succeeded)
{
return BadRequest(result.Errors);
}

if(!_roleManager.Roles.Any())
{
await _roleManager.CreateAsync(new IdentityRole("User"));
await _roleManager.CreateAsync(new IdentityRole("Admin"));
}

await _userManager.AddToRoleAsync(user, "User");

return Ok(result.Succeeded);
}

As you can understand from the code if there is not any role in the database I am adding User and Admin roles. And after that I am updating the new registering user’s role to User.

In AspNetUserRoles table it mapped the user’s Id with the given role Id:

AspNetUserRoles Table

Now If you add that [Authorize] Attribute in any endpoint it will check the user’s role if the user’s role is not equal to “User” then it will not let that user to run this endpoint it will throw an error.

That was all that I wanted to write about Identity. You can access the source code from here.

I hope the Article gave you information about how you can add Identity library to your project and how to make some Authentication operation with it. If you liked the article don’t forget to claps and follow on Medium to hear more from me. Happy Coding!!

--

--

Server Tombak
nacressoftware

Software Engineer with a relentless passion for learning and sharing knowledge. Join me on my journey to explore the ever-evolving world of technology.