This is always the case when we write some custom filter without being understanding the sequence which we should be using.
One classic example is to handle custom Unauthorized Access for application permissions at Controller Action level. Say if it user has authorization of application but some of the permission is not allowed and still it executes controller-action then it is a serious issue.
[Authorize]
SomeController
{
[ValidateApplicationPermission]
SomeAction
{
}
}
For. Eg
Using something like this, here we are trying to use filterContext with HttpContext
Solution
Use filterContext with its Result, obey filters and its context.
One classic example is to handle custom Unauthorized Access for application permissions at Controller Action level. Say if it user has authorization of application but some of the permission is not allowed and still it executes controller-action then it is a serious issue.
[Authorize]
SomeController
{
[ValidateApplicationPermission]
SomeAction
{
}
}
Problem Definition:
ValidateApplicationPermission results into 403 access denied leak. It captures access denied and tries to redirect however it is redirecting with executing existing action filter which it should not suppose to be.For. Eg
Using something like this, here we are trying to use filterContext with HttpContext
filterContext.HttpContext.Server.TransferRequest(Entities.Constants.Entities.Content.Something.Home._403.Path .GetSitecoreItemUrlPath());
Solution
Use filterContext with its Result, obey filters and its context.
filterContext.Result = new RedirectResult(Entities.Constants.Entities.Content.Something.Home._403.Path.GetSitecoreItemUrlPath());
Implementation Code Base
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[AttributeUsage(AttributeTargets.Method, Inherited = false)] | |
public class ValidateApplicationPermission : FilterAttribute, IAuthorizationFilter | |
{ | |
public enum UnauthorizeResponses | |
{ | |
RedirectTo403, | |
EmptyResult | |
} | |
private ApplicationPermissions RequiredPermission { get; } | |
private UnauthorizeResponses UnauthorisedResponse { get; } | |
public ValidateApplicationPermission(ApplicationPermissions requiredPermission, UnauthorizeResponses unauthorizeResponse = UnauthorizeResponses.RedirectTo403) | |
{ | |
RequiredPermission = requiredPermission; | |
UnauthorisedResponse = unauthorizeResponse; | |
} | |
public void OnAuthorization(AuthorizationContext filterContext) | |
{ | |
var isAuthenticated = filterContext.HttpContext.User.Identity.IsAuthenticated; | |
if (!isAuthenticated) | |
filterContext.Result = new RedirectResult(Entities.Constants.Entities.Content.Something.Home._403.Path.GetSitecoreItemUrlPath()); | |
UserContext userContext; | |
using (var scope = ServiceLocator.BeginScopeForCurrentSite()) | |
{ | |
var sessionService = scope.Resolve<ISessionService>(); | |
userContext = sessionService.Get<UserContext>(Entities.Infrastructure.Enums.SessionKeys.UserContext); | |
} | |
if (userContext == null) | |
{ | |
if (filterContext.HttpContext.Request.IsAjaxRequest()) | |
{ | |
Sitecore.Diagnostics.Log.Info("Session expired.Redirecting user to login page...", this); | |
IServiceResponse<string> response = new ServiceResponse<string>(); | |
response.RedirectUrl = Entities.Constants.Entities.Content.Something.Home.Login.Path.GetSitecoreItemUrlPath(); | |
response.Status = ServiceResponseStatuses.Redirect; | |
filterContext.Result = new JsonResult { Data = new UiServiceResponse<string>(response), JsonRequestBehavior = JsonRequestBehavior.AllowGet }; | |
filterContext.HttpContext.Response.StatusCode = 440; | |
} | |
else | |
{ | |
if (!HttpContext.Current.Response.IsRequestBeingRedirected) | |
{ | |
Sitecore.Diagnostics.Log.Info("Session expired.Redirecting user to login page...", this); | |
string returnUrl = WebUtil.AddQueryString(Entities.Constants.Entities.Content.Something.Home.Login.Path.GetSitecoreItemUrlPath(), "returnUrl", Boolean.TrueString.ToLower()); | |
WebUtil.Redirect(returnUrl); | |
} | |
} | |
return; | |
} | |
if (!userContext.ValidatePermission(RequiredPermission).HasValue) | |
{ | |
if (UnauthorisedResponse == UnauthorizeResponses.EmptyResult) | |
filterContext.Result = new EmptyResult(); | |
else | |
filterContext.Result = new RedirectResult(Entities.Constants.Entities.Content.Something.Home._403.Path.GetSitecoreItemUrlPath()); | |
} | |
} | |
} |