Best practise for optional injecting of current user

.net, asp.net-mvc, c#, dependency-injection, ninject

Solution

I assume you are talking about a situation where a non-authenticated user could try to navigate to a page that normally requires authentication, but without first going through the login process. Ninject would then be unable to inject the current user object into the controller because it's not yet known and will throw an exception.

I can see 2 options:

The first option is instead of injecting the current user, create a factory or provider that retrieves the current user details and inject this instead. The controller can then call the provider to get the current user and if the user is unavailable you can redirect to the login page.

public OrdersController(IUserProvider userProvider)
{
    this.userProvider = userProvider
}

public void DoSomething()
{
    var user = this.userProvider.GetCurrentUser();
    if (user == null)
        RedirectToLogin();

    // continue doing something
}

public class UserProvider : IUserProvider
{
    public User GetCurrentUser() { ... }
}

The problem with this option is that you'll need to do this potentially in many controllers (it's a "cross cutting concern") and you don't want to have to repeat the code that does the redirect over and over. Instead, a second option would be to use the Decorator design pattern to create an interceptor that checks for logged in users before forwarding on to the real controller.

The way I've done something similar in the past is using the Ninject Interception Extension to create an attribute that marks which controllers require authentication, like this (bit psuedo-codey):

public class AuthenticationInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        bool authenticated = // ... get the current user ...

        if (authenticated)
            invocation.Proceed();
        else
            RedirectToLoginPage(); // however you want to do this
    }
}

public class RequiresAuthenticationAttribute : InterceptAttribute
{
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return request.Context.Kernel.Get<AuthenticationInterceptor>();
    }
}

[RequiresAuthentication]
public class OrdersController : IOrdersController
{
    // assume you've already been authenticated
}

The interceptor will automatically be created whenever a class that's decorated with `RequiresAuthentication` is created and the current user credentials will be checked. If they are invalid, the request will be forwarded to the login page, otherwise it will continue as normal. This one interceptor can then be written and tested once whilst being used in many places without duplicating code.

Problem

In our ASP.NET MVC project we are using Ninject to resolve our dependencies needed by the controllers. One of these dependencies is the current user `HttpContext.Current.User.Identity`. If the user is authenticated we would like to instantiate a user object and several services which relies on it. But we would like to do this not manually but let ninject inject these instances to the controller. So we get into trouble now, since a url can be located without being authenticated of course. Then ninject tries to resolve the instances before asp.net can redirect to the login page. I can think of the solution, that we configure ninject do just inject when user is authenticated: ``` kernel.Bind<User>().ToMethod(GetUser).When(context => HttpContext.Current.User.Identity.IsAuthenticated).InRequestScope(); ``` The problem here is that even if the user is not authenticated ninject instantiates a default object, so my services crashes or needs to check the instance anyhow. Null checks would me much more acceptable but I wouldn't like to activate `AllowNullInjection` setting of Ninject. So my question is whats the best practise for doing such conditional things? Are there Ninject features I could use in these cases or shouldn't I inject these dependencies anyway?

Original source