89

I have an authorization attribute on a controller, but I'd like to turn it off on one action. I created my own authorization filter and added "Anonymous" into the Roles list. In my filter I then return true if Anonymous appears in the role list.

However, it doesn't seem to get past the login page as if the controller authorization is pre-empting anything else.

jaffa
  • 26,770
  • 50
  • 178
  • 289
  • `(1):` Not sure I understand you, some code would be good. `(2):` You can add authorization attributes on action methods. – gideon Mar 06 '12 at 09:54
  • You can create your own version of the Attribute. http://stackoverflow.com/questions/746998/override-authorize-attribute-in-asp-net-mvc – Tx3 Mar 06 '12 at 10:08
  • Gee, everybody seems to not understand you :). I understand, but I wanted a solution because I have the same issue. Have you found something in the meantime? – Adrian Marinica Dec 10 '12 at 12:03

5 Answers5

172

You can add [Authorize] To the controller class, and then add [AllowAnonymous] to the single action you don't want to be authorized. Example:

[Authorize]
public class AccountController : Controller
{
    public ActionResult Profile()
    {
        return View();
    }

    [AllowAnonymous]
    public ActionResult Login()
    {
        return View();
    }
}
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Kyle
  • 32,731
  • 39
  • 134
  • 184
3

I just did a solution using Azure ACS as the federated Identity Provider and the accepted answer didn't work for me. For those who are struggling, my solution was to bypass the security altogether for the required controller/views.

Create a new Controller/Views for those actions which you need to bypass the authorization.

And in the web.config add the following ,

 <location path="TheNameOfTheControllerYouWantToBypass">
  <system.web>
  <authorization>
    <allow users="*" />
  </authorization>
  </system.web>
 </location>
Illuminati
  • 4,539
  • 2
  • 35
  • 55
3

You can create your own version of the attribute.

There is a very similar question and there is a pretty good answer how to implement your own attribute that handles this situation.

Override Authorize Attribute in ASP.NET MVC

Btw. you could also create your controller that would have authorization by default.

Base

[Authorize]
public abstract class SecureControllerBase : Controller
{
}

Usage

public class MyController : SecureControllerBase
{
}
Community
  • 1
  • 1
Tx3
  • 6,796
  • 4
  • 37
  • 52
  • 1
    Thanks, but say I have a controller with 10 action methods requiring authorization and only 1 action without. My controller has the authorization enabled on all actions (by having authorization filter at the top of the controller definition), however I just want to turn it off on one action method. – jaffa Mar 06 '12 at 11:01
  • If you add [OptionalAuthorize] to the controller and then [OptionalAuthorize(false)] on top of the action? Does that work for you? – Tx3 Mar 06 '12 at 11:18
0

Simply add the attribute to the Actions you want to filter, and not on the controller class. By not decorating actions, they will not be filtered, provided the controller or one of its base controllers hasn't got the attribute.

AaronHS
  • 1,334
  • 12
  • 29
  • 2
    I want the exception to the rule, so turn on for the controller and off for a single action. – jaffa Mar 14 '12 at 10:58
-1

Do not add AuthorizationAttribute on your action method where ever you do not required for example.

My custom attribute

public class AuthorizationFilterAttribute : AuthorizeAttribute
{
    // Some code...
}

My controller

public class UserController : BaseController, IDisposable
{
    [AuthorizationFilterAttribute]
    public ActionResult UserList()
    {
        // Authorize attribute will call when this action is executed
    }

    public ActionResult AddUser()
    {
        // Authorize attribute will not call when this action is executed
    }
}

I hope you got my point what I am trying to say you.

============================ Updated Answer ================================

Create one more attribute like below.

public sealed class AnonymousAttribute : Attribute { }

Please put below code on your OnAuthorization method.

public override void OnAuthorization(AuthorizationContext filterContext)
{
    bool checkForAuthorization =
        filterContext.ActionDescriptor.IsDefined(typeof(AnonymousAttribute), true) ||
        filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AnonymousAttribute), true);

    if (!skipAuthorization)
    {
        base.OnAuthorization(filterContext);
    }
}
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
alok_dida
  • 1,723
  • 2
  • 17
  • 36
  • 2
    Ok but that means adding filters all over the controller actions. I like the idea of keeping the authorisation filter at the top and then disabling where I need to. Seems more robust/secure this way. – jaffa Mar 07 '12 at 09:19
  • Yeah right. Do let me know that, is it work for you or not? If it is than please mark it as an answer, so that it will be useful for others. – alok_dida Mar 07 '12 at 12:34
  • It works to get authorization on the only the actions you want, but it was not OP's question. – Kyle Feb 28 '13 at 02:47
  • @user1308743.. Agreed. But this is an alternative solution. FYI, When he posted this question at that time MVC4 is not released. :) – alok_dida Feb 28 '13 at 10:43
  • This got me started. – Chamika Goonetilaka Aug 10 '18 at 07:21