Reputation: 10078
I have the following controller with a custom authorize attribute:
[CustomAuthorize(Roles = "Editor, Admin")]
public ActionResult Test()
{
//...
}
Here is my custom authorize code:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
private readonly string[] _allowedRoles;
public CustomAuthorizeAttribute(params string[] roles)
{
_allowedRoles = roles;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
}
if (_allowedRoles.Length > 0 && !_allowedRoles.Any(user.IsInRole))
{
return false;
}
return true;
}
}
The custom authorize is returning true for even a user who is not an Editor or Admin?
I think the issue is this:
[CustomAuthorize(Roles = "Editor, Admin")]
I'm passing it as a string and I need to convert it to an array in my CustomAuthorize method???
Upvotes: 3
Views: 1862
Reputation: 247541
The current definition of the attribute makes no reference to the Roles
property and also does not populate the _allowedRoles
field.
This is why your attribute always returns true
.
Review the rafactored logic of custom attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute {
private readonly string[] _allowedRoles;
public CustomAuthorizeAttribute(params string[] roles) {
_allowedRoles = roles;
}
protected override bool AuthorizeCore(HttpContextBase httpContext) {
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var user = httpContext.User;
if (user?.Identity?.IsAuthenticated) {
if (isInRole(user, _allowedRoles)) {
return true;
}
if (!string.IsNullOrWhiteSpace(Roles)) {
var roles = Roles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (isInRole(user, roles))
return true;
}
return true;
}
return false;
}
bool isInRole(IPrincipal user, string[] roles) {
return roles.Length > 0 && roles.Any(user.IsInRole);
}
}
Which can be used like
[CustomAuthorize(Roles = "Editor, Admin")]
public ActionResult Test() {
//...
}
where the roles will be split and checked against user
Or like
[CustomAuthorize("Editor", "Admin")]
public ActionResult Test() {
//...
}
which would populate the constructor of the attribute with the parameter array
Upvotes: 1
Reputation: 3403
first you need to get the current user's roles and then check if any of the roles allow the user to access to the controller :
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
}
var userRoles = ((ClaimsIdentity)User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
if (_allowedRoles.Length > 0 && !_allowedRoles.Any(x => userRoles.Any(y => x.Equals(y)))))
{
return false;
}
return true;
}
Upvotes: 0