I'm working on using the Policies featured (in conjunction with Windows Auth). What I want to accomplish is simple, I want the user to be both authorized to access the app via windows auth, but limit access to sections of an intranet site using policies. My issue is that when I add the claim, it's being added to System.Security.Claims.ClaimsIdentity , instead of System.Security.Principal.WindowsIdentity. This is an issue because the policy.RequireClaim("MyTotallyCoolPolicyName") only searches the xxPrincipal.WindowsIdentiy. FWIW, the claims data I'm attempting to add comes from a db.
Relevant Code Below: Startup.cs services.AddScoped();
services.AddAuthorization(options =>
{
options.AddPolicy("SuperUser", policy =>
{
policy.RequireAuthenticatedUser();
policy.Requirements.Add(new UserRequirement());
policy.RequireClaim("Permission Level");
});
});
services.AddScoped<Data.Interface.IAuthorization, Data.EDL.Authorization>();
services.AddScoped<IAuthorizationHandler, UserPermissionAuthHandler>();
services.AddScoped<IClaimsTransformation, ClaimsTransformer>();
ClaimsTransformer.cs
public class ClaimsTransformer : IClaimsTransformation
{
private IHttpContextAccessor _httpContextAccessor;
public ClaimsTransformer(IHttpContextAccessor httpContext)
{
_httpContextAccessor = httpContext;
}
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal p)
{
var pp = new ClaimsPrincipal();
p.AddIdentity(new ClaimsIdentity("https://customnamehere.com/claims/permissionclaim", "Permission Level", "1"));
if(p.Claims.Any(a => a.ValueType.Contains("Permission")))
{
}
return Task.FromResult(p);
}
}
and this is what it looks like:
Is there a way to switch to the other claims when using the RequireClaims? Or am I using it wrong?
Fwiw, I don't need to "Add" a new user to the system. The user already exists. So the UserManager class doesn't apply to me.
Adding controller method:
[Authorize(AuthenticationSchemes ="Windows", Policy = "SuperUser")]
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
Adding UserRequirement class:
public class UserRequirement : IAuthorizationRequirement
{
public string EmailAddress { get; private set; }
public string UserName { get; set; }
public int PermissionID { get; set; }
public bool HasPermission { get; set; }
public bool IsActive { get; set; } = false;
public string PermissionName { get; set; }
}
It shouldn't matter to what identity the claims are part of. But the claim types should match as expected.
You can use custom names for claim types like role
, name
, but you can also use the WIF standards . Just make sure that the types matches. User.IsInRole, etc. expect claims of a certain type.
Take a look at the code below. Notice the ClaimsIdentity. I think that is why your code didn't work.
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal p)
{
var id = new ClaimsIdentity("TransformerClaimsMiddleware",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role");
// I don't know what your intention is, but it seems more logical to me to
// add new claims to the identity, instead of adding the same claim with
// another type.
var claims = p.Claims.Where(a => a.ValueType.Contains("Permission")).ToList();
// Add the claims to the new identity
claims.ForEach(c => id.AddClaim(new Claim("https://customnamehere.com/claims/permissionclaim", c.Value)));
p.AddIdentity(id);
return Task.FromResult(p);
}
}
Also change this:
RequireClaim("Permission Level")
to
RequireClaim("https://customnamehere.com/claims/permissionclaim")
Please let me know if that helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.