0

Question: Is OnAuthorization called for every request? If not, where can I check for session timeout before Authorize attributes are called?

Background: I need a way to determine if session exists and has not timed out. I want to do this on every method call for every controller in my app. I need to do this before authorization filters are called because I keep a hashset of permissions in session and my authorize attribute looks at these permissions. I need to do this for every request, regardless of whether an authorize attribute is applied or not.

A couple answers I've read (one cited below) state to override OnActionExecuting in a base controller. This makes sense however I've found OnActionExecuting is not calleed until after AuthorizeCore in the filter attribute is called.

The approach I've arrived at thus far is to check for session in a base controller and check for permission in an authorize attribute.

BaseController.cs:

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        // This base does two things:
        // 1.)  Ensures that Session exists
        // 2.)  Ensures that the Security object exists and is initalized.

        HttpContextBase httpContext = filterContext.HttpContext;

        // Check if session exists

        if (httpContext.Session == null)
            filterContext.Result = Redirect(core.SecurityConstants.SessionTimeoutRedirectURL);
        else
        {
            if(!Security.IsInitialized())
                filterContext.Result = Redirect(core.SecurityConstants.PermissionDeniedRedirectURL);
            else if (httpContext.Session.IsNewSession)  // check if a new session id was generated
            {
                // If it says it is a new session, but an existing cookie exists, then it must have timed out
                string sessionCookie = httpContext.Request.Headers["Cookie"];

                if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
                {
                    if (httpContext.Request.IsAjaxRequest())
                    {
                        filterContext.HttpContext.Response.StatusCode = 401;
                        httpContext.Response.End();
                    }
                    filterContext.Result = Redirect(core.SecurityConstants.SessionTimeoutRedirectURL);
                }
            }
        }
        base.OnAuthorization(filterContext);
    }

SecurityAttribute.cs:

public class SecurityAttribute : AuthorizeAttribute
{
    public Permission Permission { get; set; }

    public SecurityAttribute(Permission permission)
    {
        Permission = permission;
    }


    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        base.AuthorizeCore(httpContext);
        return Security.HasPermission(Permission);
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);

        //if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
        //{
            filterContext.RequestContext.HttpContext.Response.Redirect(SecurityConstants.PermissionDeniedRedirectURL);
        //}
    }
}

References

When OnAuthorization method is called?

With ASP.NET MVC redirect to login page when session expires

Community
  • 1
  • 1

1 Answers1

0

Maybe following works for you, add it in Global.asax

protected void Application_AcquireRequestState()
{
    if (Context.Session!=null && Context.Session.IsNewSession)
    {
        //do something
    }
}
hammadmirza
  • 156
  • 6
  • This looks like a very good idea so I basically copied my base controller code into the method as suggested. Unfortunately it appears that IsNewSession is being set to true and the user is being redirected as if their session had timed out. This does not occur when the code is in base controller. –  Mar 03 '15 at 19:10
  • the session timeout problem appears to be related to chrome looking for favicon.ico. This is the correct answer. –  Mar 04 '15 at 23:12