Click here to Skip to main content
Click here to Skip to main content
Go to top

ASP.NET MVC - AuthorizeWithExemptionsAttribute

, 26 Aug 2010
Rate this:
Please Sign up or sign in to vote.
This base controller will secure all your actions except those which will be marked as UnsecuredAction.

Introduction

In this article, I'll provide you with a solution for securing ASP.NET MVC application's controllers in a way that all the actions are secured except those you define as unsecure (by default, all the actions are unsecure unless you define them as secure).

I encountered a problem in the ASP.NET MVC authorization model, which is built as opt-in. You can secure an action or a controller using the [Authorize] attribute. The problem is that if you want to secure a whole controller and make some actions in that controller as not secured - you can't.

This article will explain to you how you can secure a whole controller and make some actions as not secured within it.

This project was written in Visual Studio 2010 as an ASP.NET MVC 2 project.

Background

I was looking for a solution to that problem, and couldn't find a reasonable one. Other solutions suggested to:

  • Move the unsecured actions to another controller (not secured)
  • Write the AuthorizeCore method to be dependent on the Action's names
  • Put the [Authorize] attribute on all the actions except the non-secured actions

In this article, I'll provide you with my solution to this problem.

Using the Code

To use the code, you'll need your controllers to put any [CustomAuthorize] attribute which inherits from AuthorizeWithExemptionsAttribute on your controllers. Calling any action on this controller will include an authorization check. If you want to mark an Action as non-secured, just put the [UnsecuredAction] Attribute above it.

Explanation

The core of this solution is in the [AuthorizeWithExemptions] Attribute in the OnAuthorization method. This method checks if the called Action has the UnsecuredActionAttribute, and if it does, it marks filterContext.HttpContext.SkipAuthorization as true.

public override void OnAuthorization(AuthorizationContext filterContext)
{
    ActionDescriptor action = filterContext.ActionDescriptor;
    bool IsUnsecured = action.GetCustomAttributes(
                         typeof(UnsecuredActionAttribute), true).Count() > 0;

    //If doesn't have UnsecuredActionAttribute - then do the authorization
    filterContext.HttpContext.SkipAuthorization = IsUnsecured;

    base.OnAuthorization(filterContext);
}

Then, CustomAuthorizeAttribute performs the authorization check only if SkipAuthorization is false.

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
  if (httpContext.SkipAuthorization)
  {
      return true;
  }

  // Do any authorization logic here
  return httpContext.Request.QueryString["password"] == "password";
}

* Of course, never provide the password in the QueryString, it was made like that just for the ease of the example.

So now, when you try to invoke the secured controller, you get the HTTP error code 401: Unauthorized.

And the unsecured controller works without any authorization required.

History

  • 23rd August, 2010: Initial post
  • 24th August, 2010: Updated article and source code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Maxim Novak
Team Leader Leverate
Israel Israel
No Biography provided

Comments and Discussions

 
GeneralDrop the inheritance requirement Pinmemberpaul.vencill23-Aug-10 18:05 
GeneralRe: Drop the inheritance requirement Pinmembersakrank23-Aug-10 18:12 
GeneralRe: Drop the inheritance requirement PinmemberMaxim Novak24-Aug-10 9:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140905.1 | Last Updated 26 Aug 2010
Article Copyright 2010 by Maxim Novak
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid