I have an action I want to restrict only to role "Admin". I did it like this:
[Authorize(Roles = "Admin")]
public ActionResult Edit(int id)
After manually going under Controller/Edit/1 path I'm redirected to login page. Well, that isn't bad maybe, but I want to show 404 instead of it and try to stick using attributes for it. Is that possible?
Is that possible?
Sure, you could write a custom authorize attribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Shared/401.cshtml"
};
}
}
and then use it:
[MyAuthorize(Roles = "Admin")]
public ActionResult Edit(int id)
Remark: you probably want to show a 401 or 403 page if the user is not authorized instead of 404 which is for file not found.
In response to @Daniel's comment on my comment to @Darin's answer this is my implementation:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
string cookieName = FormsAuthentication.FormsCookieName;
if (!filterContext.HttpContext.User.Identity.IsAuthenticated ||
filterContext.HttpContext.Request.Cookies == null ||
filterContext.HttpContext.Request.Cookies[cookieName] == null
)
{
HandleUnauthorizedRequest(filterContext);
return;
}
var authCookie = filterContext.HttpContext.Request.Cookies[cookieName];
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(',');
var userIdentity = new GenericIdentity(authTicket.Name);
var userPrincipal = new GenericPrincipal(userIdentity, roles);
filterContext.HttpContext.User = userPrincipal;
base.OnAuthorization(filterContext);
}
// Redirects unauthorized users to a "401 Unauthorized" page
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Shared/Error/401.cshtml"
};
}
}