I'm in a bit of a bind with implementing Roles in ASP.NET MVC 5. I am attempting to log in as a user that does not have a role required to access the area of the application I'm trying to reach. What I would expect in this scenario is, I'm redirected to the login page again, and will be until I enter a set of credentials that do have access or I navigate to another area of the application.
What is actually happening is that the application appears to go into a login redirect loop, debugging through reveals that the Login action is being called multiple times.
Here is the login action:
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
This results in an error generated by IIS:
HTTP Error 404.15 - Not Found
The request filtering module is configured to deny a request where the query string is too long.
The query string looks like this:
http://localhost/MyApplication/Account/Login?ReturnUrl=%2FMyApplication%2FAccount%2FLogin%3FReturnUrl%3D%252FMyApplication%252FAccount%252FLogin%253FReturnUrl%253D%25252FMyApplication%25252FAccount%25252FLogin%25253FReturnUrl%25253D%2525252FMyApplication%2525252FAccount%2525252FLogin%2525253FReturnUrl%2525253D%252525252FMyApplication%252525252FAccount%252525252FLogin%252525253FReturnUrl%252525253D%25252525252FMyApplication%25252525252FAccount%25252525252FLogin%25252525253FReturnUrl%25252525253D%2525252525252FMyApplication%2525252525252FAccount%2525252525252FLogin%2525252525253FReturnUrl%2525252525253D%252525252525252FMyApplication%252525252525252FAccount%252525252525252FLogin%252525252525253FReturnUrl%252525252525253D%25252525252525252FMyApplication%25252525252525252FAccount%25252525252525252FLogin%25252525252525253FReturnUrl%25252525252525253D%2525252525252525252FMyApplication%2525252525252525252FAccount%2525252525252525252FLogin%2525252525252525253FReturnUrl%2525252525252525253D%252525252525252525252FMyApplication%252525252525252525252FAccount%252525252525252525252FLogin%252525252525252525253FReturnUrl%252525252525252525253D%25252525252525252525252FMyApplication%25252525252525252525252FAccount%25252525252525252525252FLogin%25252525252525252525253FReturnUrl%25252525252525252525253D%2525252525252525252525252FMyApplication%2525252525252525252525252FAccount%2525252525252525252525252FLogin%2525252525252525252525253FReturnUrl%2525252525252525252525253D%252525252525252525252525252FMyApplication%252525252525252525252525252FAccount%252525252525252525252525252FLogin%252525252525252525252525253FReturnUrl%252525252525252525252525253D%25252525252525252525252525252FMyApplication%25252525252525252525252525252FAccount%25252525252525252525252525252FLogin%25252525252525252525252525253FReturnUrl%25252525252525252525252525253D%2525252525252525252525252525252FMyApplication%2525252525252525252525252525252FAccount%2525252525252525252525252525252FLogin%2525252525252525252525252525253FReturnUrl%2525252525252525252525252525253D%252525252525252525252525252525252FMyApplication%252525252525252525252525252525252F
The only change I've made going from a working solution (albeit without role based authorization) to my current broken situation is adding the following above the controller that I'm redirected to on a successful login:
[Authorize(Roles = "Staff")]
As I said previously, the user I'm logging in as is not in this role, but I would expect a sane, single redirect to Login, without the looping.
Edit: requested bu @dima, the details of authorization applied through filters... I have the following:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AuthorizeAttribute());
}
}
However, I have tested the application with and without this line in place and the redirect loop continues unabated.
While this question is old, I had the same problem and found a solution.
Originally, I had added the same AuthorizationAttribute filter, and found myself in the same loop. I then took it away and began adding the authorize attribute to individual controllers, and found that the infinite loop only happened when adding the authorize attribute to my home controller. It turns out my
HomeController
was getting called after myAccountController
.The Problem
In my
_Layout.cshtml
, I was calling the following:The layout page would correctly render the body, but when it got to this, it was hitting a controller method that had an authorization attribute. This caused the redirect to the
Account/Login
.Adding the
AllowAnonymous
attribute to theLeftNav
action resolved the issue.The Solution
Make sure your
Login
view and layouts do not call any actions that have an authorize attribute.Since discovering this, I've created a custom layout for my unauthorized requests to avoid any more potential issues like this.
If anyone's having issues MVC going back to login with out any error, whe running in Visual Studio/IIS Express make sure the project is set to use SSL and use the https local host address when logging in.
I was working on the same example given in the question but the answer (marked) given by @silencedmessage couldn't solve my situation despite i disconnected all the links between the
Home
controller andAccount
controller and betweenAccount
controller and_layout
view. If someone is facing this same situation as me, I recommend adding following step to the solution:Since the
AuthorizeAttribute
in this very example is applied globally, all its action methods are secured by default and don't allow 'annonymous' access. In this very example,[AllowAnnonymous]
attribute is only applied to[HttpGet]
login Action Method. It is not applied to [HttpPost] login ActionMethod and sinceAuthorizeAttribute
is applied globally, it is securing[HttpPost]
login ActionMethod as well, hence[HttpPost]
login ActionMethod is not executing, and you are being redirected to[HttpGet]
login ActionMethod infinitely.By simply adding
[AllowAnnonymous]
to[HttpPost]
login ActionMethod solved my situation.Hope it helps.