I'm trying to do some custom authorization so I created a controller overriding the OnAuthorization
method. I also applied the Authorize
attribute to this controller.
The question is why is the OnAuthorization
method called BEFORE the basic forms authentication process?
I would like to authorize the user after he is authenticated. Am I missing something?
Here is the code:
[Authorize]
public class AuthorizationController : Controller
{
protected override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
List<string> allowedControllers = new List<string>() { "SecurityController" };
List<string> allowedActions = new List<string>() { "Index" };
string controllerName = filterContext.Controller.GetType().Name;
string actionName = filterContext.ActionDescriptor.ActionName;
if (!allowedControllers.Contains(controllerName)
|| !allowedActions.Contains(actionName))
{
filterContext.Result = View("UnauthorizedAccess");
}
}
}
The controller that I tested with is something like:
public class SecurityController : AuthorizationController
{
public ActionResult Index()
{
return View();
}
public ActionResult AnotherIndex()
{
return View();
}
}
Right-click on the solution and add a new class. Enter the class name and click on Add. Next Inherite Attribute, IAuthorizationFilter to CustomAuthorization class which has overridden the OnAuthorization method. The OnAuthorization Method has the AuthorizationFilterContext parameter.
Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. We can apply the filter globally, at the controller level, or at the level of individual actions.
Authorization in ASP.NET Core is controlled with AuthorizeAttribute and its various parameters. In its most basic form, applying the [Authorize] attribute to a controller, action, or Razor Page, limits access to that component to authenticated users. Now only authenticated users can access the Logout function.
This attribute is useful when you want to use the Authorize attribute on a controller to protect all of the actions inside, but then there is this single action or one or two actions that you want to unprotect and allow anonymous users to reach that specific action.
One of the first things the AuthorizeAttribute
does is check to see if the user is authenticated. If they are not then that is when a redirect to the login page will be issued.
The AuthorizeAttribute
basically wraps the authentication check in with the authorization piece:
protected virtual bool AuthorizeCore(HttpContextBase httpContext) {
if (httpContext == null) {
throw new ArgumentNullException("httpContext");
}
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated) {
return false;
}
When you use the AuthorizeAttribute with no roles/users as you do in your example ([Authorize]), it is basically just checking to make sure the user is authenticated in this case.
I would probably change your code to override the AuthorizeAttribute instead of doing this code in your controller. You can do the following:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.Result = CreateResult(filterContext);
}
protected ActionResult CreateResult(AuthorizationContext filterContext)
{
var controllerContext = new ControllerContext(filterContext.RequestContext, filterContext.Controller);
var controller = (string)filterContext.RouteData.Values["controller"];
var action = (string)filterContext.RouteData.Values["action"];
// any custom model here
var model = new UnauthorizedModel();
// custom logic to determine proper view here - i'm just hardcoding it
var viewName = "~/Views/Shared/Unauthorized.cshtml";
return new ViewResult
{
ViewName = viewName,
ViewData = new ViewDataDictionary<UnauthorizedModel>(model)
};
}
}
Following is a sample for Custom Authorization Attribute.
public class AuthLogAttribute:AuthorizeAttribute
{
public string View { get; set; }
public AuthLogAttribute()
{
View = "AuthorizeFailed";
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
IsUserAuthorized(filterContext);
}
private void IsUserAuthorized(AuthorizationContext filterContext)
{
// If the Result returns null then the user is Authorized
if(filterContext.Result ==null)
return;
//If the user is Un-Authorized then Navigate to Auth Failed View
if(filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var vr = new ViewResult();
vr.ViewName = View;
ViewDataDictionary dict = new ViewDataDictionary();
dict.Add("Message", "Sorry you are not Authorized to Perform this Action");
vr.ViewData = dict;
var result = vr;
filterContext.Result = vr;
}
}
}
Your Controller will be like following,
[AuthLog(Roles ="Manager")]
public ActionResult Create()
{
var product = new Product();
return View(product);
}
Finally create new Shared view Call "AuthorizeFailed".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With