Application authentication
.NET Core ASP.NET Core Identity C# SQL Visual Studio Web API

Managing User Roles with the ASP.NET Core Identity API

Welcome to today’s post.

In this post I will be showing how to manage user roles within a custom identity provider API using .NET Core.

To keep this post brief I will go over some API URLs that would be useful for role management and show how these are implemented and tested.

Here are a list of useful API methods we will use for role management:

api/ManageUser/UserList
api/ManageUser/RoleList
api/ManageUser/AddRole
api/ManageUser/DeleteRole
api/ManageUser/GetUserRoles

With the above API we run the following requests and get the results as shown:

Obtain a list of users:

HTTP GET: 
http://localhost/BookLoan.Identity.API/api/ManageUser/UserList

[
    {
        "id": "cc85629b-4cf1-4238-8134-6c5683c5ced7",
        "userName": "test@bookloan.com",
        "email": "test@bookloan.com",
        "firstName": null,
        "lastName": null,
        "dob": "0001-01-01T00:00:00",
        "password": null
    }
]

Obtain all user roles:

HTTP GET: http://localhost/BookLoan.Identity.API/api/ManageUser/RoleList

[
    "Admin",
    "Member",
    "Manager"
]

Adding a role to a specific user account:

HTTP POST: http://localhost/BookLoan.Identity.API/api/ManageUser/AddRole

{
    "loginName": "test@bookloan.com",
    "SelectedRole": "Admin"
}

Remove a role from a specific user account:

HTTP POST: http://localhost/BookLoan.Identity.API/api/ManageUser/DeleteRole

{
    "loginName": "test@bookloan.com",
    "SelectedRole": "Member"
}

Obtain user roles for specific user account:

HTTP GET: http://localhost/BookLoan.Identity.API/api/ManageUser/GetUserRoles/
admin@bookloan.com

[
    "Admin",
    "Member",
    "Manager"
]

The above API can be tested using POSTMAN.

For the API api/ManageUser/UserList the implementation is shown below:

API Controller

// GET: ManageUsers/UserList
[HttpGet("api/[controller]/UserList")]
public async Task<ActionResult> UserList()
{
   return Ok(await _userRoleService.GetUsers());
}

Role Service

public async Task<List<BookLoan.Models.ManageUserViewModels.UserViewModel>> GetUsers()
{
   List<BookLoan.Models.ManageUserViewModels.UserViewModel> 
   userViews = new List<Models.ManageUserViewModels.UserViewModel>();
   userManager.Users.ToList().ForEach(async u =>
   {
      Task<bool> isInRoleResult = 
         userManager.IsInRoleAsync(u, "Admin");
       bool isInRole = isInRoleResult.GetAwaiter().GetResult();
       if (isInRole == false)
          userViews.Add(
             new Models.ManageUserViewModels.UserViewModel()
             {
                ID = u.Id,
                UserName = u.UserName,
                Email = u.Email
             }
          );
   });
   return userViews;
}

We can test the UserList() API method Running in POSTMAN:

For the AddRole() and DeleteRole() methods, the implementations are below:

API Controller

[HttpPost("api/[controller]/AddRole")]
public async Task<ActionResult> AddRole(
   [FromBody]Models.ManageUserViewModels.UserRoleConfirmAction model)
{
    try
    {
       	await _userRoleService.AddUserToRole(
              model.LoginName, 
              model.SelectedRole);
       	return Ok();
    }
    catch
    {
       	return BadRequest();
    }
}

[HttpPost("api/[controller]/DeleteRole")]
public async Task<ActionResult> DeleteRole([FromBody] 
   Models.ManageUserViewModels.UserRoleConfirmAction model)
{
   try
   {
       await _userRoleService.DeleteUserFromRole(
           model.LoginName, 
           model.SelectedRole);
       return Ok();
    }
    catch
    {
       	return BadRequest();
    }
}

Role Service

In the role service we use the RoleStore, UserManager and RoleManager to retrieve user account data and update role details to the UserRoles table.

public async Task AddUserToRole(string userName, string role)
{
   var roleManager = new RoleStore<IdentityRole>(db);
   var user = await userManager.FindByEmailAsync(userName);
   bool isInRole = await this.IsUserInRole(userName, role); 
   if (!isInRole)
   {
       if ((role == "Member") || (role == "Manager"))
       {
           var memberRole = roleManager.FindByNameAsync(role);
           var memberUser = userManager.FindByEmailAsync(userName);
           if (memberRole != null && memberUser != null)
           {
               db.UserRoles.Add(new IdentityUserRole<string>()
               {
                   RoleId = memberRole.Result.Id.ToString(),
                   UserId = memberUser.Result.Id.ToString()
               });
               await db.SaveChangesAsync();
           }
       	}
    }
}

In the removal of role from user account we utilize the identity API to remove a role from the UserRole table.

public async Task DeleteUserFromRole(string userName, string role)
{
   var roleManager = new RoleStore<IdentityRole>(db);
   var user = await userManager.FindByEmailAsync(userName);
   bool isInRole = await this.IsUserInRole(userName, role); 
   if (isInRole)
   {
       if ((role == "Member") || (role == "Manager"))
       {
           var memberRole = roleManager.FindByNameAsync(role);
           var memberUser = userManager.FindByEmailAsync(userName);
           if (memberRole != null && memberUser != null)
           {
               var currUserRole = db.UserRoles.Where(
                   r => r.UserId == memberUser.Result.Id &&
                        r.RoleId == 
                          memberRole.Result.Id).SingleOrDefault();
               if (currUserRole != null)
               {
                  db.UserRoles.Remove(currUserRole);
                  await db.SaveChangesAsync();
               }
            }
        }
     }
}

For the GetUserRoles() API method, the implementation is shown:

API Controller

[HttpGet("api/[controller]/GetUserRoles/{userName}")]
public async Task<ActionResult> GetUserRoles(string userName)
{
   List<string> userRoles = new List<string>();
   try
   {
         userRoles = await _userRoleService.GetUserRoles(userName);
       	 return Ok(userRoles);
   }
   catch
   {
         return BadRequest();
   }
}

Role Service

When retrieving roles, we utilize the ASP.NET identity API UserManager method IsInRoleAsync() to retrieve user roles, filtering out the non-admin role.

public async Task<List<BookLoan.Models.ManageUserViewModels.UserViewModel>> GetUsers()
{
   List<BookLoan.Models.ManageUserViewModels.UserViewModel> 
   userViews = new List<Models.ManageUserViewModels.UserViewModel>();
   userManager.Users.ToList().ForEach(
      async u =>
      {
         Task<bool> isInRoleResult = 
            userManager.IsInRoleAsync(u, "Admin");
         bool isInRole = isInRoleResult.GetAwaiter().GetResult();
         if (isInRole == false)
            userViews.Add(new            
               Models.ManageUserViewModels.UserViewModel()
       	 {
            ID = u.Id,
            UserName = u.UserName,
            Email = u.Email
         });
      });
      return userViews;
}

We can test the above using POSTMAN:

Adding a role:

Deleting a role:

Retrieving user roles:

We can also verify the data in the SQL AspNetUserRoles table that ASP.NET Identity uses to store our user roles:

Another thing to remember is to set up the user manager and identity stores for ASP.NET Identity to be able to use the UserManager API and RoleStore API on the ApplicationUser and IdentityRole data contexts you will need to setup the identity for these stores in the ConfigureServices() method within startup.cs using the AddIdentity() extension method:

services.AddIdentity<ApplicationUser, IdentityRole>()
   .AddEntityFrameworkStores<ApplicationDbContext>()
   .AddDefaultTokenProviders();

Once this has been setup and your services have been setup for dependency injection, they can be injected into your services for use to manage your roles and users.

That’s all for today’s post.

I hope this post has been useful and informative.

Social media & sharing icons powered by UltimatelySocial