C# API Controller Custom Filter with HttpActionContext Redirect to controller?

5.6k views Asked by At

Is there a way to create a custom filter with an API controller to redirect to a MVC controller?

After looking around a bit his is what i have.

public class APIHasOneOfThesePermissions : ActionFilterAttribute
{
    protected UserManager<ApplicationUser> UserManager { get; set; }
    private SAMPortal.DAL.SAMPortalContext db = new DAL.SAMPortalContext();
    public string[] Permissions { get; set; }

    public APIHasOneOfThesePermissions(string[] Permissions)
    {
        this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.db));
        this.Permissions = Permissions;
    }
    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        string userID = HttpContext.Current.User.Identity.GetUserId();
        var CurrUser = db.Users.Include(u => u.Role.Permissions).Where(user => user.Id.Equals(userID)).FirstOrDefault();

        bool hasPermission = false;

        foreach (string x in Permissions)
        {
            if (hasPermission == false)
            {
                hasPermission = CurrUser.HasPermission(x);
            }
        }

        if (hasPermission == false)
        {
            filterContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
        }

        base.OnActionExecuting(filterContext);
    }
}

However when i execute the code it doesn't redirect them to the error page. Ideally i would like to redirect to a specify non-API controller is that possible?

1

There are 1 answers

2
Jure On

I've created AuthorizeRedirectAttribute in one of my projects like this:

using System;
using System.Net;
using System.Web.Mvc;

namespace MyNamespace.Attributes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeRedirectAttribute : AuthorizeAttribute
    {
        public string RedirectUrl = "~/Error/Forbidden403";

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
        }

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

            var httpContext = filterContext.RequestContext.HttpContext;
            var request = httpContext.Request;
            var response = httpContext.Response;

            // If AJAX request, just return appropriate code
            if (request.IsAjaxRequest())
            {
                if (filterContext.HttpContext.User.Identity.IsAuthenticated)
                    response.StatusCode = (int)HttpStatusCode.Forbidden;
                else
                    response.StatusCode = (int)HttpStatusCode.Unauthorized;
                response.SuppressFormsAuthenticationRedirect = true;
                response.End();
            }

            // Otherwise check if authenticated, and if not redirect to specified url
            if (httpContext.User.Identity.IsAuthenticated)
            {
                httpContext.Response.Redirect(RedirectUrl);
            }
        }
    }
}

Then I've used it like this

[AuthorizeRedirect(Roles = "Administrator")]
public class MyController : Controller
{
}

In this case I've decorated whole controller with this attribute. It can also be applied to single controller function, if necessary. Basically what it does is, it checks whether logged on user is in role Administrator. If it is not, user is redirected to "~/Error/Forbidden403" action (returning simple view displaying user has not enough permissions). Hope it helps.

You could also implement checking your own permissions, as you did in your code.