Question

In .Net MVC4 I'm using a subclassed AuthorizeAttribute to redirect all requests to the "Change Password" page when a user's password has been reset as follows:

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // Call base class method first
        base.OnAuthorization(filterContext);

        // Only redirect if password change is required and the requested action
        // is not "Change Password"
        if (!passwordChangeRequired
            && !(filterContext.Controller is ApplicantController &&
                 MVC.Applicant.ActionNames.ChangePassword.Equals(filterContext.ActionDescriptor.ActionName)))
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "controller", MVC.Applicant.Name },
                    { "action", MVC.Applicant.ActionNames.ChangePassword }
                });
        }
    }

Have just written this code it seems to work but am not yet confident and wondering if it could be simplified.

Especially regarding controllers and actions - the project is using T4MVC so do both need to be included separately in the check and redirect or could they somehow be combined?

Also should the base.OnAuthorization call be made at the start or end (or neither)?

Grateful for any pointers...

Was it helpful?

Solution

I ended up modifying this slightly to use ActionFilterAttribute instead of AuthorizeAttribute.

In case this is of use to anyone here is the code:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class ChangePasswordAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Filter on executing
    /// </summary>
    /// <param name="filterContext">The current action context</param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        // Don't redirect to "Change Password" action if it is the current action
        if (filterContext.Controller is ApplicantController &&
            MVC.Applicant.ActionNames.ChangePassword.Equals(filterContext.ActionDescriptor.ActionName))
        {
            return;
        }

        // Redirect if password change is required
        if ((filterContext.HttpContext.Session[SessionKeys.PasswordChangeRequired] != null) 
            && (bool)filterContext.HttpContext.Session[SessionKeys.PasswordChangeRequired])
        {
            // Save route in session so the user can be redirected appropriately after a successful password change
            RouteValueDictionary routeValues = new RouteValueDictionary(filterContext.RouteData.Values);
            filterContext.HttpContext.Session[SessionKeys.PasswordChangeRouteValues] = routeValues;

            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "controller", MVC.Applicant.Name },
                    { "action", MVC.Applicant.ActionNames.ChangePassword }
                });
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top