All Projects → mo-esmp → Dynamicrolebasedauthorizationnetcore

mo-esmp / Dynamicrolebasedauthorizationnetcore

Licence: gpl-3.0
Dynamic Role-Based Authorization in ASP.NET Core MVC 2.1, 3.1 and 5.0

Projects that are alternatives of or similar to Dynamicrolebasedauthorizationnetcore

Aspnetcoreratelimit
ASP.NET Core rate limiting middleware
Stars: ✭ 2,199 (+1163.79%)
Mutual labels:  asp-net-core
Firewall
ASP.NET Core middleware for IP address filtering.
Stars: ✭ 159 (-8.62%)
Mutual labels:  asp-net-core
Storedprocedureefcore
Entity Framework Core extension to execute stored procedures
Stars: ✭ 164 (-5.75%)
Mutual labels:  asp-net-core
Vuejsssrsample
ASP.NET Core Vue.js server-side rendering sample:
Stars: ✭ 146 (-16.09%)
Mutual labels:  asp-net-core
Aspnetcore
ASP.NET Core Extension Library
Stars: ✭ 152 (-12.64%)
Mutual labels:  asp-net-core
Active Directory B2c Dotnetcore Webapp
An ASP.NET Core web application that can sign in a user using Azure AD B2C, get an access token using MSAL.NET and call an API.
Stars: ✭ 160 (-8.05%)
Mutual labels:  asp-net-core
Fluentvalidation.blazor
Fluent Validation-powered Blazor component for validating standard <EditForm> 🌌 ✅
Stars: ✭ 140 (-19.54%)
Mutual labels:  asp-net-core
Lyniconanc
Lynicon CMS for ASP.Net Core for .Net Standard 2.0/2.1 and .Net 4.6.1/4.6
Stars: ✭ 173 (-0.57%)
Mutual labels:  asp-net-core
Formhelper
ASP.NET Core - Transform server-side validations to client-side without writing any javascript code. (Compatible with Fluent Validation)
Stars: ✭ 155 (-10.92%)
Mutual labels:  asp-net-core
Identitymanager2
Development tool for administering users and roles
Stars: ✭ 164 (-5.75%)
Mutual labels:  asp-net-core
Westwind.aspnetcore.markdown
An ASP.NET Core Markdown support library that provides Markdown parsing, a Markdown TagHelper and Markdown Page Handler Middleware
Stars: ✭ 148 (-14.94%)
Mutual labels:  asp-net-core
52abp.school
52ABP实战系列教程入门-52ABP学校管理系统
Stars: ✭ 152 (-12.64%)
Mutual labels:  asp-net-core
Dockerize.net
.NET Cli Tool to package your .NET Core Application into a docker image: 'dotnet dockerize'
Stars: ✭ 162 (-6.9%)
Mutual labels:  asp-net-core
Blazorise
Blazorise is a component library built on top of Blazor with support for CSS frameworks like Bootstrap, Bulma, AntDesign, and Material.
Stars: ✭ 2,103 (+1108.62%)
Mutual labels:  asp-net-core
Netcorecms
NetCoreCMS is a modular theme supported Content Management System developed using ASP.Net Core 2.0 MVC. Which is also usable as web application framework. This project is still under development. Please do not use before it's first release.
Stars: ✭ 165 (-5.17%)
Mutual labels:  asp-net-core
Aspnetcoresample
Asp.Net Core Samples.
Stars: ✭ 143 (-17.82%)
Mutual labels:  asp-net-core
Bitframework
Full stack dev framework for C# / TypeScript / JavaScript developers
Stars: ✭ 158 (-9.2%)
Mutual labels:  asp-net-core
Angular 7 Project With Asp.net Core Apis
Angular 7 Project with ASP.NET CORE APIS | Angular Project
Stars: ✭ 174 (+0%)
Mutual labels:  asp-net-core
Netcore Boilerplate
Boilerplate of API in .NET Core 3.1
Stars: ✭ 166 (-4.6%)
Mutual labels:  asp-net-core
Security.identity
.NET DevPack Identity is a set of common implementations to help you implementing Identity, Jwt, claims validation and another facilities
Stars: ✭ 165 (-5.17%)
Mutual labels:  asp-net-core

Dynamic Role-Based Authorization in ASP.NET Core MVC 2.1, 3.1 and 5.0 NuGet

You already know how role-based authorization works in ASP.NET Core.

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
}

But what if you don't want hardcode roles on the Authorize attribute or create roles later and specify in which controller and action it has access without touching source code?

DynamicAuthorization helps you authorize users without hardcoding role(s) on the Authorize attribute with minimum effort. DynamicAuthorization is built at the top of ASP.NET Core Identity and uses identity mechanism for managing roles and authorizing users.

Install the DynamicAuthorization.Mvc.Core NuGet package

Install-Package DynamicAuthorization.Mvc.Core

or

dotnet add package DynamicAuthorization.Mvc.Core

Then, add AddDynamicAuthorization() to IServiceCollection in Startup.ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services
        .AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = false)
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
        
    services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")

You can set the default admin username via DefaultAdminUser config to access everywhere without creating a default admin role and its access.

Then install JSON or SQLSever store to save role access.

To install DynamicAuthorization.Mvc.JsonStore NuGet package

Install-Package DynamicAuthorization.Mvc.JsonStore

or

dotnet add package DynamicAuthorization.Mvc.JsonStore
public void ConfigureServices(IServiceCollection services)
{
        
    services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")
        .AddJsonStore(options => options.FilePath = "FilePath");

Role access will be saved in a JSON file and you can specify the file path FilePath config.

Or install SQLServer store DynamicAuthorization.Mvc.MsSqlServerStore NuGet package

Install-Package DynamicAuthorization.Mvc.MsSqlServerStore

or

dotnet add package DynamicAuthorization.Mvc.MsSqlServerStore
public void ConfigureServices(IServiceCollection services)
{
        
    services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")
        .AddSqlServerStore(options => options.ConnectionString = "ConnectionString");

You can decorate controllers and actions with DisplayName attribute to show the user a more meaningful name instead of controller and action name.

[DisplayName("Access Management")]
public class AccessController : Controller
{

    // GET: Access
    [DisplayName("Access List")]
    public async Task<ActionResult> Index()
}

You can also the default UI for managing roles and assigning roles to users if you don't want to implement them by yourself.

Install the DynamicAuthorization.Mvc.Ui NuGet package

Install-Package DynamicAuthorization.Mvc.Ui

Then AddUi to DynamicAuthorization registration:

services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")
        .AddJsonStore(options => options.FilePath = "FilePath")
        .AddUi();

Use http://<your-app>/role url to manage roles and assign access to a role.

create project

Use http://<your-app>/userrole url to assign roles to users.

You can also use a custom TageHelper to check whether the user has access to view content or not. create a custom tag helper that inherits from SecureContentTagHelper

[HtmlTargetElement("secure-content")]
public class MySecureContentTagHelper : SecureContentTagHelper<ApplicationDbContext>
{
    public MySecureContentTagHelper(
        ApplicationDbContext dbContext,
        DynamicAuthorizationOptions authorizationOptions,
        IRoleAccessStore roleAccessStore
        )
        : base(dbContext, authorizationOptions, roleAccessStore)
    {
    }
}

In each view wrap a content or an anchor tag inside secure-content tag:

<ul class="nav navbar-nav">
    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
    
    <secure-content asp-area="" asp-controller="Role" asp-action="Index">
        <li><a asp-area="" asp-controller="Role" asp-action="Index">Role</a></li>
    </secure-content>
    <secure-content asp-area="" asp-controller="Access" asp-action="Index">
        <li><a asp-area="" asp-controller="Access" asp-action="Index">Access</a></li>
    </secure-content>
</ul>

Don't forget to add your tag halper namespace to _ViewImports.cshtml:

@using SampleMvcWebApp
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, SampleMvcWebApp

If you extended IdentityUser or you changed user and role key, you should pass user and role type too. for example:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { ... }
public class MySecureContentTagHelper : SecureContentTagHelper<ApplicationDbContext, ApplicationUser> { ... }

or

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int> { ... }
public class MySecureContentTagHelper : SecureContentTagHelper<ApplicationDbContext, ApplicationUser, ApplicationRole, int> { ... }

If you don't want to use the default UI, follow the below steps to discover controllers and actions and give access to the role and then assign role(s) to the user. The next step is discovering controllers and actions. IMvcControllerDiscovery return all controllers and actions that decorated with [Authorize] attribute. IMvcControllerDiscovery.GetControllers() method returns list of MvcControllerInfo:

public class MvcControllerInfo
{
    public string Id => $"{AreaName}:{Name}";

    public string Name { get; set; }

    public string DisplayName { get; set; }

    public string AreaName { get; set; }

    public IEnumerable<MvcActionInfo> Actions { get; set; }
}

public class MvcActionInfo
{
    public string Id => $"{ControllerId}:{Name}";

    public string Name { get; set; }

    public string DisplayName { get; set; }

    public string ControllerId { get; set; }
}

The next step is creating a role to assign access to it. Use RoleManager<> to create role and IRoleAccessStore to store role access.

var role = new IdentityRole { Name = "RoleName" };
var result = await _roleManager.CreateAsync(role);

var controllers = _mvcControllerDiscovery.GetControllers();
var roleAccess = new RoleAccess
{
    Controllers = controllers.First(),
    RoleId = role.Id
};
await _roleAccessStore.AddRoleAccessAsync(roleAccess);

The final step is assigning a created role to a user:

var user = await _userManager.FindByIdAsync("someId");
await _userManager.AddToRolesAsync(user, new [] { "RoleName" });

And now the user only can access those controllers and actions that his roles can access.

Here is an example to create a role and assign access to the role.

public class RoleViewModel
{
    [Required]
    [StringLength(256, ErrorMessage = "The {0} must be at least {2} characters long.")]
    public string Name { get; set; }

    public IEnumerable<MvcControllerInfo> SelectedControllers { get; set; }
}

[DisplayName("Role Management")]
public class RoleController : Controller
{
    private readonly IMvcControllerDiscovery _mvcControllerDiscovery;
    private readonly IRoleAccessStore _roleAccessStore;
    private readonly RoleManager<IdentityRole> _roleManager;

    public RoleController(
        IMvcControllerDiscovery mvcControllerDiscovery,
        IRoleAccessStore roleAccessStore,
        RoleManager<IdentityRole> roleManager
        )
    {
        _mvcControllerDiscovery = mvcControllerDiscovery;
        _roleManager = roleManager;
        _roleAccessStore = roleAccessStore;
    }

    // GET: Role/Create
    [DisplayName("Create Role")]
    public ActionResult Create()
    {
        var controllers = _mvcControllerDiscovery.GetControllers();
        ViewData["Controllers"] = controllers;

        return View();
    }
    
    // POST: Role/Create
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(RoleViewModel viewModel)
    {
        if (!ModelState.IsValid)
        {
            ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
            return View(viewModel);
        }

        var role = new IdentityRole { Name = viewModel.Name };
        var result = await _roleManager.CreateAsync(role);

        if (!result.Succeeded)
        {
            foreach (var error in result.Errors)
                ModelState.AddModelError("", error.Description);

            ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
            return View(viewModel);
        }

        if (viewModel.SelectedControllers != null && viewModel.SelectedControllers.Any())
        {
            foreach (var controller in viewModel.SelectedControllers)
                foreach (var action in controller.Actions)
                    action.ControllerId = controller.Id;

            var roleAccess = new RoleAccess
            {
                Controllers = viewModel.SelectedControllers.ToList(),
                RoleId = role.Id
            };
            await _roleAccessStore.AddRoleAccessAsync(roleAccess);
        }

        return RedirectToAction(nameof(Index));
    }
}

Checkout samples to view full implementation.

To implement DynamicAuthorization step by step by yourself checkout manual branch.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].