Search code examples
.netasp.net-mvcclaims-based-identityadfsclaims

Redirect loop with .Net MVC Authorize attribute with ADFS Claims


I have a problem configuring ADFS with my .Net MVC 5 app.

I have configured my project in VS 2015 to use claims and it works ok, but I have an issue.

I can sign in, ussing ADFS, I can check user roles etc. The problem occures when i try to use

[Authorize(Roles="somenonExistingRole")]

despite that I'm already authenticated I am redirected to ADFS page, when Authentication takes place again, and I'm redirected to my page, where loop occures. Page send me to ADFS portal , ADFS redirects my to portal, and after few tries i get an error from ADFS ( to many requests )

Do I have to implement something like Role provider by myself? or i need to configure something extra. Maybe i could just limit number of tries? Why am I redirected to ADFS when I have my roles allready?

there is not much to show actualy in the code, ut as requested: the controller that im testing:

 public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        [Authorize]
        public ActionResult About()
        {
            var u = HttpContext.User;


            if (u.IsInRole("/"))
            {
                ViewBag.Message = "User is in role.";
            }
            else
            {
                ViewBag.Message = "User is NOT in role.";
            }

            return View();
        }
        [Authorize(Roles = "/nonexistingRole")]
        public ActionResult Contact()
        {

            ViewBag.Message = "Your contact page.";

            return View();
        }
    }

and the configure auth section

public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseWsFederationAuthentication(
        new WsFederationAuthenticationOptions
        {
            Wtrealm = realm,
            MetadataAddress = adfsMetadata, 

        });
}

Solution

  • To fix the loop problem, you should override the AuthorizeAttribute.

    By Default, MVC returns a 401 Unauthorized when a user's roles do not meet the AuthorizeAttribute requirements. This initializes a reauthentication request to the identity provider. Since the user is already logged in, AAD returns to the same page, which then issues another 401, creating a redirect loop. Here, we override the AuthorizeAttribute's HandleUnauthorizedRequest method to show something that makes sense in the context of our application.

    This class was generated when creating a new MVC project using VS 2015 :

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {        
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                //One Strategy:
                //filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
    
                //Another Strategy:
                filterContext.Result = new RedirectToRouteResult(
                    new RouteValueDictionary(
                        new
                        {
                            controller = "Error",
                            action = "ShowError",
                            errorMessage = "You do not have sufficient priviliges to view this page."
                        })
                    );
            }
            else
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }
    }