16

I have an ASP.NET MVC application with a controller that looks something like this:

[Authorize]
public class MyController : Controller
{
IMyRepository myRepository;
public MyController(IMyRepository myRepository)
{
   this.myRepository = myRepository;
}

...
}

I have noticed that this constructor gets called prior to authenticating the user, so if you are visiting the page for the first time the constructor is called prior to redirecting you to the login screen. There are many problems with this, the login page loads slower, the site has greater exposure to DOS attacks, and I'm a little nervous about unauthenticated, unauthorized users being able to invoke code 'behind the walls' sort of speak.

I could check the incomming request in the constructor and bail unless the user is authorized, but I'm using IOC (Windsor) which makes that a bit tricky, my repository is going to be initialized regardless of whether or not I store the instance, so I'd be left checking authentication in each repository's constructor. Is there an easy way to get .NET MVC to authenticate the user prior to invoking the constructor? I'm thinking something like adding [PrincipalPermission(SecurityAction.Demand, Authenticated = true)] to the controller, but there might be a better way still.

EDIT:

Ok, not too happy about it, but the show must go on for now. I cannot delay initializing the repository until some later point in time from within the controller. When your controller uses IOC as in my example, you get an already instantiated implementation of your repository interface at the time that the controller is instantiated. If I had control over the repository being created, I could easily just call IsAuthenticated, no need for a new method. In order to take control of the repository initialization you would have to implement some sort of lazy/late initialization in the repository itself in each implementation. I do not like this solution because it adds needless complexity and more importantly coupling between the controller and repository. The repository implementation(s) may be used in other contexts where lazy initialization doesn't make sense IMHO.

Paul
  • 6,188
  • 1
  • 41
  • 63
  • 1
    Provided that your constructor for your IMyRepository implementation was lightweight then I don't see a major issue here (i.e. if it's an expensive process to setup the actual connection to your backing store then do it lazily, i.e. on first read/write). You no more exposed that with the login page as that too is instantiating a controller and probably accessing a backing store to verify credentials. – Lazarus Dec 16 '10 at 12:34
  • 1
    @Lazarus But what if a dependency on my controller requires access to a non-null user name (i.e. the user needs to be authenticated at that point). Currently I'm using a `Lazy` instance for that, but I hate it. I think it would make too much sense to authenticate the user before him reaching the controller. – julealgon Jun 09 '15 at 00:02

4 Answers4

7

The controller needs to be instantiated before authorization happens because it can act as its own authorization filter via the OnAuthorization method. Changing that behavior would involve replacing some core parts of the mvc pipeline. Is there a particular reason why you think the AuthorizedAttribute might not do its job?

Another option you could consider is initializing your repository in the OnActionExecuting of your controller method instead of in the constructor.

OneManBand
  • 528
  • 5
  • 24
marcind
  • 52,944
  • 13
  • 125
  • 111
  • My controllers have rather heavy constructors, and I don't want unauthenticated users to be able to initiate the code. I understand that authorization cannot occur before the controller is instantiated, I just want authentication performed beforehand. I'll post whatever I find here when I'm finished. – Paul Dec 16 '10 at 22:44
  • Oh, if you just want to prevent unauthenticated users from even reaching your controller then you could look into writing a custom route that would not match for unauthenticated clients. – marcind Dec 16 '10 at 22:57
  • 4
    Another option you could consider is initializing your repository in the OnActionExecuting of your controller method instead of in the constructor. – marcind Dec 17 '10 at 00:35
  • In the case of heavy constructors, you have already pinpointed the real issue. As we can do little about how MVC works, we can only change the things we control. Which is to remove the heavy work away from your constructors. – Thomas Eyde Dec 30 '10 at 05:14
  • @marcind; The OnActionExecuting is the perfect answer. If I had enough rep I'd edit your answer to put it in there. – flytzen Jan 29 '11 at 11:40
2

You can use HttpModules (or HttpHandler) to authenticate the request earlier in the pipeline.

EDIT

With the introduction of OWIN you can configure the entire request pipeline middleware and put authorization at whatever stage you want. Same idea as above but a bit easier to implement.

Paul
  • 6,188
  • 1
  • 41
  • 63
0

Paul,

the instantiation of the controller is many many processes ahead of any actions on the controller being callable. even if the would be attacker attempted to benefit from this time lapse between instantiation and the login-screen, the controller action would only be able to run if the action had the authority to do so i.e. i'm assuming that your actions or controller all have the [Authorize] attribute on them.

I don't think you need worry too much about this and can rest easy, tho' i understand your obvious curiosity.

jim tollan
  • 22,305
  • 4
  • 49
  • 63
0

In terms of DOS attacks, it really should not matter -- after the first hit, which one sees alot when developing, the controller instantiation should be cheap. Well, unless you are DDOSing yourself by having the constructor do actual work such as pre-caching database lookups . . .

Wyatt Barnett
  • 15,573
  • 3
  • 34
  • 53