4

I am trying to implement AuthorizationHandler in .net core 2.0 where i need to authorize the user and based on the condition wanted to redirect to different action methods within my application validation works ok but how i can redirect user to the Access Denied or Login page when authorization failed.

 protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasPermissionRequirement requirement)
    {
        var controllerContext = context.Resource as AuthorizationFilterContext;

        if (sessionManager.Session.sysUserID <= 0)
        {
            controllerContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Account", action = "Login", area = "" }));

            return Task.FromResult(0);
        }


            if (Utilities.GetInt32Negative(PermissionID) == 1 || Utilities.GetInt32Negative(PermissionID) == -1)
            {
                if (!PagePath.Equals("~/"))
                    controllerContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "NoAccess", area = "" }));
            }

            context.Succeed(requirement);
        }
        else
        {
            if (!PagePath.Equals("~/"))
                controllerContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "NoAccess", area = "" }));
        }

        return Task.FromResult(0);
    }
Azhar
  • 281
  • 5
  • 17
  • You are not supposed to be doing redirects from authorization requirements. Setup your authentication handler to redirect to the correct pages for when authorization fails. This is usually done in `Startup`, where you define which authentication methods you support etc. – juunas Sep 07 '17 at 09:33

2 Answers2

15

I found the solution and i hope this will help someone looking for the similar, in custom authorization we can redirect to any desired controller action using the AuthorizationFilterContext and with the RedirectToActionResult

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasPermissionRequirement requirement)
{
    // Get the context       
    var redirectContext = context.Resource as AuthorizationFilterContext;
    //check the condition 
    if (!result)
    {
        redirectContext.Result = new RedirectToActionResult("AccessDenied", "Home", null);
        context.Succeed(requirement);
        return Task.CompletedTask;
    }
    context.Succeed(requirement);
    return Task.CompletedTask;
}
Azhar
  • 281
  • 5
  • 17
1

First you can configure the conditions for login page/authentication by creating a custom scheme like this.

public class SampleScheme : AuthenticationHandler<AuthenticationSchemeOptions>
{
    public const string SchemeName = "sample";

    public SampleScheme(IOptionsMonitor<AuthenticationSchemeOptions> options, 
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) 
                    : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (myconditions){
            return AuthenticateResult.Fail("error message");
        }
        else {
            return await Context.AuthenticateAsync
            (CookieAuthenticationDefaults.AuthenticationScheme); 
           // return default cookie functionality. 
        }
    }

}

Then you can create a similar class for Access denied/forbidden access as well (lets say SampleScheme2). Finally you can set them up in your startup.cs

services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = SampleScheme.SchemeName;
    options.DefaultForbidScheme = SampleScheme2.SchemeName;
})
.AddCookie(options => {
    options.LoginPath = "/login";
    options.AccessDeniedPath = "/forbidden";
})
.AddScheme<AuthenticationSchemeOptions, SampleScheme>(SampleScheme.SchemeName, o => { });
.AddScheme<AuthenticationSchemeOptions, SampleScheme2>(SampleScheme2.SchemeName, o => { });

I hope the code is self explanatory enough. There are some variations so let me know if this is not exactly what you were going for.

Neville Nazerane
  • 5,682
  • 3
  • 31
  • 68