ASP.net MVC 4 global Authorize filter forcing login on an AllowAnonymous action

13,877

Solution 1

Is it possible that the _Layout file used by the ResetPasswordForUser view is invoking an Action in your Controller (e.g. in a menu?) that hasn't been decorated with AllowAnonymous?

This would cause this type of behaviour.

Solution 2

It sounds like you could have a non-anonymous @Html.Action or Html.RenderAction in your layout, which is causing your page to redirect to login.

Edit: Deleted old answer as it was incorrect and not useful for anyone coming to see it.

Solution 3

I don't know if adding that global authorize filter conflicts with AllowAnonymous. The way I set up my project is to have a Base Controller that has the [Authorize] attribute set at the controller level.

All my controllers inherit from this BaseController except for ones that require anonymous access, usually my AccountController and my MarketingController. Those simply inherit from Controller and then I can set [Authorize] at the Action level.

Share:
13,877
forhas
Author by

forhas

Updated on June 04, 2022

Comments

  • forhas
    forhas almost 2 years

    In my .NET MVC 4 I'm adding a global filter in order to secure my controllers. This is done using:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
       filters.Add(new HandleErrorAttribute());
       filters.Add(new System.Web.Mvc.AuthorizeAttribute());
    }
    

    Which is invoked from my Global.cs class.

    My Web.config file contains a standard configuration:

    <authentication mode="Forms">
         <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
    

    My Login action is decorated with [AllowAnonymous] in order to allow anonymous users to login.

    So far so good, everything works great. Here is my Login action:

    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }
    

    Now, I wanted to add a reset-password page which also just like the login page should be available to anonymous users. I created me action (under the same controller of the Login action) and decorated it with the [AllowAnonymous] decoration:

    [AllowAnonymous]
    public ActionResult ResetPasswordForUser(string message = "")
    {
        ViewBag.message = message;
        return View();
    }
    

    Then created the corresponding view.

    I added this link to my Login page:

    @Html.ActionLink("Forgot your password?", "ResetPasswordForUser", "Account")
    

    In runtime, as I click this link using an anonymous user I do get to the ResetPasswordForUser action, but when returning the view the Login action gets invoked and I can never actually get to the desired view. For some reason my request gets intercepted even though I'm using the [AllowAnonymous] decoration.

    Am I missing something here?

    Thanks in advance

    Update1:

    As per Darin Dimitrov request adding my ResetPasswordForUser view:

    @using TBS.Models
    @model TBS.ViewModels.ResetPasswordForUserViewModel
    
    @{
        ViewBag.Title = "Reset Password";
    }
    
    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
    
        <table class="edit-table rounded bordered" style="width: 400px">
            <tr>
                <td class="label-td">
                    @Html.LabelFor(m => m.Username)
                </td>
                <td>
    
                    @Html.TextBoxFor(m => m.Username)
                    @Html.ValidationMessageFor(model => model.Username)
                </td>
            </tr>
            <tr>
                <td class="label-td">
                    @Html.LabelFor(m => m.Password)
                </td>
                <td>
                    @Html.Password("Password")
                    @Html.ValidationMessageFor(model => model.Password)
                </td>
            </tr>
            <tr>
                <td colspan="2" style="text-align: center">
                    <input type="submit" value="Reset" />
                </td>
            </tr>
        </table>
    }