Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching a failed authorization policy

In .Net Core 2, suppose there is an authorization policy that checks that specific claims exist for the user:

public class CompletedProfileRequirement : AuthorizationHandler<CompletedProfileRequirement>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CompletedProfileRequirement requirement)
    {
        // Check that all required claims exist
        if (/* invalid user claims */) {
            context.Fail();
        }

        context.Succeed(requirement);
        return Task.FromResult(0);
    }
}

And we stick the policy check on top of an MVC controller:

[Authorize(Policy = "CompletedProfile")]
public class HomeController : Controller
{
     // Controller stuff
}

How can I write an IAuthorizationFilter so that we can catch a failure on this particular CompletedProfileRequirement policy so that we can redirect the user to a page where they may complete their profile?

like image 541
jungos Avatar asked Nov 17 '22 15:11

jungos


1 Answers

According to the authorization documentation, it's possible to access the MVC context from your AuthorizationHandler:

Frameworks such as MVC or Jabbr are free to add any object to the Resource property on the AuthorizationHandlerContext to pass extra information.

For example, MVC passes an instance of AuthorizationFilterContext in the Resource property. This property provides access to HttpContext, RouteData, and everything else provided by MVC and Razor Pages.

Therefore, you can do something like this:

public class CompletedProfileRequirement : AuthorizationHandler<CompletedProfileRequirement>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CompletedProfileRequirement requirement)
    {
        // Check that all required claims exist
        if (/* invalid user claims */) {

            // retrieve MVC context
            if (context.Resource is AuthorizationFilterContext mvcContext)
            {
                // we still need to mark the requirement as succeeded, 
                // otherwise responde code is 401 unauthorized
                context.Succeed(requirement);

                // HTTP 302 temporary redirect to your page
                mvcContext.HttpContext.Response.Redirect("/Home/Wherever", false);
                return Task.FromResult(0);
            }

        }

        context.Succeed(requirement);
        return Task.FromResult(0);
    }
}
like image 165
Métoule Avatar answered Dec 20 '22 22:12

Métoule