reactjsasp.net-coresingle-page-applicationasp.net-core-identity

How can I implement role-based authorization in a React & ASP.NET Core project?


I used ASP.NET Core Identity in my project.

Project repository :

https://github.com/hmahdavi921/ReactTypeScriptApp1

Programs.cs file :

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using ReactApp1.Server.Data;
using System.Security.Claims;

namespace ReactTypeScriptApp1.Server
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            var connectionString = builder.Configuration.GetConnectionString("ApplicationDbContextConnection") ?? throw new InvalidOperationException("Connection string 'ApplicationDbContextConnection' not found.");

            builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));

            builder.Services.AddAuthorization();
            builder.Services.AddIdentityApiEndpoints<ApplicationUser>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            // Add services to the container.
            builder.Services.AddControllers();

            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            var app = builder.Build();

            app.UseDefaultFiles();
            app.UseStaticFiles();

            app/*.MapGroup("/account")*/.MapIdentityApi<ApplicationUser>();

            app.MapPost("/logout", async (SignInManager<ApplicationUser> signInManager) =>
            {
                await signInManager.SignOutAsync();
                return Results.Ok();
            }).RequireAuthorization();

            app.MapGet("/pingauth", (ClaimsPrincipal user) =>
            {
                var email = user.FindFirstValue(ClaimTypes.Email); // get the user's email from the claim
                return Results.Json(new { Email = email }); ; // return the email as a plain text response
            }).RequireAuthorization();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();

            app.UseAuthorization();

            app.MapControllers();

            app.MapFallbackToFile("/index.html");

            app.Run();
        }
    }
}

I want to develop this project to support role-based authorization.

How can I do this?


Solution

  • You could create role related controller like following:

    Add "RoleManager" service

    builder.Services.AddIdentityApiEndpoints<ApplicationUser>()
        .AddRoles<IdentityRole>()
        .AddUserManager<UserManager<ApplicationUser>>()
        .AddRoleManager<RoleManager<IdentityRole>>() 
        .AddEntityFrameworkStores<ApplicationDbContext>();
    

    AccountController.cs

        [ApiController]
        public class AccountController : ControllerBase
        {
            private readonly UserManager<ApplicationUser> _userManager;
            private readonly RoleManager<IdentityRole> _roleManager;
    
            public AccountController(UserManager<ApplicationUser> userManager,RoleManager<IdentityRole> roleManager)
            {
                this._userManager = userManager;
                this._roleManager = roleManager;
            }
    
    
            //create a role named "developer"
            [HttpPost("createRole")]
            public async Task CreateRole(string roleName)
            {
                var role = new IdentityRole { Name = "roleName" };
                await _roleManager.CreateAsync(role);
    
            }
    
    
            //add an email to "developer"
            [HttpPost("addToRole")]
            public async Task AddToRole(string email,string roleName)
            {
                var user=await _userManager.FindByEmailAsync(email);
                if (user != null)
                { 
                    await _userManager.AddToRoleAsync(user, roleName); 
                }
            }
    
        }
    

    Then After you login with this account which has been added a role "developer" , you could pass the [Authorize(Roles = "Developer")]