21

Building an MVC3 application, and TPTB want us to use their custom authorization provider. However, during development this auth provider is kind of a pain, since it will either give an error til you shut down/restart the browser, or it will require you to re-log o on every compile.

For now, I just added <authentication mode="None"/> to the web.config, which works fine until I encounter an action or controller that uses the [Authorize(Roles = "Admin")] filter (it can be any role, not just Admin). When it hits one of those, it just renders a blank page.

Is there a way globally and temporarily turn these filters off? Or just give the user all roles while I'm in development?

EDIT

Let me clarify- I'm actually porting over a large app from MVC2 to MVC3. It has lots of [Authorize(Roles="Admin")] and [Authorize(Roles="Admin,Editor")] throughout it. I'd rather not change all of those if possible.

Should I just create a small custom role provider that gives all roles automatically?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Jamie M
  • 870
  • 1
  • 8
  • 18
  • 1
    Anri's answer is better, because it does not allow to use http proxy exploit to get admin right on the server. – AgentFire Jan 24 '13 at 11:12

4 Answers4

32

You could write a custom Authorize filter which will not perform any checks if the request is coming from localhost:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext.Request.Url.IsLoopback)
        {
            // It was a local request => authorize the guy
            return true;
        }

        return base.AuthorizeCore(httpContext);
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks, this is what I ended up doing. I realized quickly that a search/replace of the Authorize attribute was a lot easier than anything else I was considering! – Jamie M Dec 07 '12 at 17:45
  • 3
    what about rather checking Request.IsLocal ? I think it's more "bulletproof". – mare Apr 17 '14 at 08:59
  • 2
    You should add a #if DEBUG around the return entire if block -- otherwise you're opening up a potential data loss issue in production. What's to stop a nefarious admin going to IE in production and typing http://127.0.0.1/refundCC?CC=1234689&amount=infinity – stevieg Jan 24 '18 at 06:17
  • I often like to do `if (Debugger.IsAttached)` .. for cases like this – Simon_Weaver May 09 '18 at 19:21
17

You can inherit from AuthorizeAttribute and separate realizations with #if DEBUG directive.

public class MyAuthorizeAttribute: AuthorizeAttribute
{
#if DEBUG
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return true;
    }
#endif
}

Or #define YOUR_OWN_FLAG to turn behavior on and off in any build, debug or release.

Anri
  • 6,175
  • 3
  • 37
  • 61
  • Sorry, I am new to MVC, where do you put the above code? Every single controller? Startup Class? – AliAzra Mar 04 '19 at 13:41
  • Each controller, yes, although not that this is an answer from 6 years ago, I don't use .NET for 4 years now and have no idea what is the right way to do it today. – Anri Mar 04 '19 at 17:09
  • "although not" = "although note" – Anri Mar 04 '19 at 17:16
8

For Web API:

public class MyAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        return actionContext.Request.RequestUri.IsLoopback || base.IsAuthorized(actionContext);
    }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • Testing for the Loopback is awesome haha why didnt I think of that – Moritz Schmidt Apr 18 '17 at 08:20
  • 1
    For those of us who don't write our own attributes very often... the above code is defining a custom attribute which you only have to do once (like in your base controller). To use the custom authorize attribute put this code on your controller (or base controller): `[MyAuthorize(Roles="Admin")]` – goku_da_master Sep 12 '19 at 23:21
1

I was also looking for this and end up resolving like below code. You could just add AllowAnonymousFilter in development environment which will disable authorization in development environment.

if (env.IsDevelopment()) {
services.AddMvc(opts =>
{
   opts.Filters.Add(new AllowAnonymousFilter());
});
} else {
 services.AddMvc();
}
sandy
  • 438
  • 4
  • 8