11

I am migrating applications away from the ASP.Net MVC 5 framework to the new .Net Core 2.1.

I used Windows Authentication with a Custom RoleProvider in the MVC 5 Projects as shown in the link below.

ASP.NET MVC How to create a custom role provider

How do I accomplish the same in Core 2.1 as it does not seem to contain RoleProvider capability?

Every example I come across uses Individual Accounts with IdentityUser and IdentityRole.

My custom tables for User and Roles :

public class User
{
    public User() { UserRoles = new HashSet<UserRole>(); }

    [Key]
    public string Id { get; set; }

    [StringLength(50)]
    [Required]
    public string Logon { get; set; } //The users Active Directory Username

    public bool Active { get; set; }

    public ICollection<UserRole> UserRoles { get; set; }

}


public class Role
{
    public Role() { UserRoles = new HashSet<UserRole>(); }

    [Key]
    public string Id { get; set; }

    public string Name { get; set; }

    public ICollection<UserRole> UserRoles { get; set; }
}

Edit:

I've added a CustomClaimsPrincipal which goes like:

public class CustomClaimsPrincipal : ClaimsPrincipal
{
    private readonly ApplicationDbContext _context;

    public CustomClaimsPrincipal(ApplicationDbContext context)
    {
        _context = context;
    }

    public override bool IsInRole(string role)
    {
        var currentUser = ClaimsPrincipal.Current.Identity.Name;

        IdentityUser user = _context.Users.FirstOrDefault(u => u.UserName.Equals(currentUser, StringComparison.CurrentCultureIgnoreCase));
            //(ApplicationUser)_context.Users.FirstOrDefault(u => u.UserName.Equals(currentUser, StringComparison.CurrentCultureIgnoreCase));

        var roles = from ur in _context.UserRoles.Where(p => p.UserId == user.Id)
                    from r in _context.Roles
                    where ur.RoleId == r.Id
                    select r.Name;
        if (user != null)
            return roles.Any(r => r.Equals(role, StringComparison.CurrentCultureIgnoreCase));
        else
            return false;
    }
}

and added to Startup.cs

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

services.AddScoped<ClaimsPrincipal, CustomClaimsPrincipal>();

But it still seems to be taking the original ClaimsPrincipal IsInRole function instead of the override which I believe is why I'm getting the error message "The trust relationship between the primary domain and the trusted domain failed."

1
  • The duplicate you mention is for Individual Accounts which uses IdentityUser which is not used in Windows Authentication Commented Aug 16, 2018 at 10:25

2 Answers 2

8

I had the same problem - the solutions given in the post weren't helpful but the comments pointed me in the right direction. You need to add claims to your ClaimsPrincipal.

Step 1: Create a ClaimsTransformer - Replace "Admin" and add a separate claim for each role you fetch from your database

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;

public class ClaimsTransformer : IClaimsTransformation
{ 
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var ci = (ClaimsIdentity) principal.Identity;
        var c = new Claim(ci.RoleClaimType, "Admin");
        ci.AddClaim(c);
        return Task.FromResult(principal);
    }
}

Step 2: Add your ClaimsTransformer to the ConfigureServices method of Startup.cs

services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(configuration =>
{
    configuration.RootPath = "ClientApp/dist";
});

services.AddSingleton<IClaimsTransformation, ClaimsTransformer>();

Step 3: You can now add Role based Authorization attributes within your Controllers

[Authorize(Roles = "Admin")]
[HttpGet("[action]/{id}")]        
public User GetUser([FromRoute] int id)
{
    UserLogic ul = new UserLogic();
    return ul.GetUser(id);
}
Sign up to request clarification or add additional context in comments.

2 Comments

How did you get this to work? I did the same thing and I get "The trust relationship between the primary domain and the trusted domain failed"?
@CoderSteve did you ever figure this out? I'm getting the same problem.
4

Managing custom permissions in net core is usually done via claims. You can do this via aspnet identity( How to add claims in ASP.NET Identity) or you can write your own middleware.

Once you have claims, you need to create Policies. This is done via the Startup.cs class in the ConfigureServices method.

services.AddAuthorization(options =>
        {
            options.AddPolicy("HR", policy => policy.RequireClaim("HRTeam"));
            options.AddPolicy("Helpdesk", policy => policy.RequireClaim("HelpdeskTeam"));
        });

And then decorate your controllers/actions with the Authorize attribure

[Authorize(Policy="Helpdesk")]
public class HelpDeskController : Controller

6 Comments

I've added claims but its still not working as expected. Can you please see above for the edit?
I don't think you need to override the ClaimsPrincipal, you need to add Claims to it when you authenticate
Claims and Roles with and without Policies are all valid schemes for managing Authorization.
@ste-fu could you expand on this? I'm having the same problem and I'm not sure what you mean by "Adding claims when you authenticate"? Currently I enable Windows Authentication using this line: services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
can we add multiple policy like this [Authorize(Policy="Helpdesk,Supervisor")] ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.