I am creating a Windows Authentication app but the roles sit within the custom database and not on the AD so I created a custom ClaimsPrincipal to override the User.IsInRole() function that usually looks at the AD for roles.
However, when running the application it still seems to be using the original code and not my CustomClaimsPrincipal. I get the error "The trust relationship between the primary domain and the trusted domain failed".
In ASP.Net MVC 5 I used a Custom RoleProvider which is essentially what I am trying to replicate here.
CustomClaimsPrincipal.cs
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));
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;
}
}
Startup.cs
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>();
services.AddScoped<ClaimsPrincipal,CustomClaimsPrincipal>();
Not sure if the above code in Startup.cs is the correct way to override the ClaimsPrincipal as I'm new to the .Net Core framework.
I think I would tackle that problem differently: instead of trying to have the instance of
ClaimsPrincipal
talk to the database to figure out if they belong to a specific role, I would modify theClaimsPrincipal
and add the roles they belong to in theClaimsPrincipal
instance.To do so, I would use a feature that is unfortunately not well documented. The authentication pipeline exposes an extensibility point where once the authentication is done, you can transform the
ClaimsPrincipal
instance that was created. This can be done through theIClaimsTransformation
interface.The code could look something like:
For full disclosure, the
TransformAsync
method will run every time the authentication process takes place, so most likely on every request, also meaning it will query the database on every request to fetch the roles of the logged-in user.The advantage of using this solution over modifying the implementation of
ClaimsPrincipal
is that theClaimsPrincipal
is now dumb and not tied to your database. Only the authentication pipeline knows about it, which makes things like testing easier as you could, for example, new-up aClaimsPrincipal
with specific roles to make sure they do or don't have access to specific actions, without being tied to the database.