Best practise for optional injecting of current user - c#

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?

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.

Just as a simple auth and non auth answer that some may find useful.
kernel.Bind<ICustomUser>()
.To<User>()
.When(ctx => HttpContext.Current.User.Identity.IsAuthenticated)
.InRequestScope();
kernel.Bind<ICustomUser>()
.To<Guest>()
.When(ctx => !HttpContext.Current.User.Identity.IsAuthenticated)
.InRequestScope();
Otherwise anything more complex Adam Rodgers awnser is better :)

Related

.NET Core WebAPI dependency injection resolve null

I use .NET Core WebAPI with dependency injection and multiple authentication schemas (http basic, access keys, JWT). I inject some business services which require some authenticated user data. If user is authenticated by any of auth middleware, DI works fine. If the user is not authenticated, DI cannot resolve some services. I need DI to return null.
How is that possible? Code bellow will result in exception, null is not allowed as result.
services.AddTransient<IMasterRepository>(serviceProvider =>
{
var _serviceFactory = new RepositoriesFactory(Configuration);
if (!Authenticated)
{
return null;
}
return _serviceFactory.CreateMasterRepository();
});
Also, I cannot return 401 in auth middleware, because another middleware may success (expl: cannot return 401 in http basic auth middleware because next one, JWT, may success)
Also, I cannot add "authentication required" check after all auth middlewares because some controllers are public (no authentication / dependency injection required).
Any advice?
Thanks!
There's no problem in registering an implementation as null. It's only in resolving that you will have a problem.
In other words, if you register:
services.AddTransient<IMasterRepository>(provider => null);
And then try:
private readonly IMasterRepository _repository;
public SomeController(IMasterRepository repository)
{
_repository = repository;
}
You will get an InvalidOperationException at runtime, with a message similar to:
Unable to resolve service for type 'MyApp.IMasterRepository' while attempting to activate 'MyApp.Controllers.SomeController'
However, there is a simple workaround. Rather than injecting the interface, inject an IEnumerable of that interface:
private readonly IMasterRepository _repository;
public SomeController(IEnumerable<IMasterRepository> repositories)
{
_repository = repositories.First(); // (using System.Linq)
}
You might think it should be FirstOrDefault, however there will indeed be a single item containing the null you registered.
This approach works because DI in ASP.Net Core supports registering multiple implementations of a given type and doesn't distinguish between null and object instances at time of registration.
Do keep in mind that even though this works, it's not recommended because now the _repository variable is potentially nullable, and a null check must be used every time it is accessed. For example: if (_repository != null) { _repository.DoSomething(); } or _repository?.DoSomething();. Most people do not expect to write code like that.
This covers the DI part of the question. But if indeed the issue is strictly with auth then ste-fu's answer describes a more appropriate approach.
The default DI framework does not allow for the factory delegate to return null by design.
Consider null object pattern by creating a NullObject derived from the interface
public class NullRepository : IMasterRepository {
public static readonly IMasterRepository Empty = new NullRepository();
public NullRepository () { }
//...implement members that do nothing and may return empty collections.
}
that does nothing when invoked.
services.AddTransient<IMasterRepository>(serviceProvider => {
IMasterRepository result = NullRepository.Empty;
var _serviceFactory = new RepositoriesFactory(Configuration);
if (Authenticated) {
result = _serviceFactory.CreateMasterRepository();
}
return result;
});
Checking for null now becomes
//ctor
public SomeClass(IMasterRepository repository) {
if(repository == NullRepository.Empty)
//...throw
//...
}
To my mind, this sounds like a problem with your dependency setup.
All your auth Middleware should be setting the ClaimsPrincipal on the HttpContext as part of the Invoke method if the authentication is successful.
Whilst a service may need to be able to access the ClaimsPrincipal in order to function correctly, you can do this by injecting IHttpContextAccessor in the constructor and enabling it in the ConfigureServices method in Startup.cs.
Getting the DI container to return null would just mean that you have to make lots of null checks all over your code. Ensuring that the ClaimsPrincipal is correctly set means that you can leverage the [Authorize] attribute to control access to particular Controllers or methods or setup Policy-based authorization which should return the correct status codes after all the auth middleware has run.
While you could create a wrapper class that is able to hold the service instance or null -OR- you could inject a dummy service in case the user is not authenticated, it's not recommended from a clean-code perspective. Both solutions would be a code smell as for the first: you would have to place null checks everywhere, even in places where you'd expect the service. And the latter: it seems like the code could actually use the service, but it's not clear a dummy service will be provided.
To keep your code clean, I'd just move the public routes, that are not requiring those services, to a separate controller class (with the same route as they have now) that does not depend on the service. This way, you can just register the repository as-is and avoid magic trickery.

How to dynamically create and inject services in ASP.NET 5?

I'm in a situation where the classic functionality of vnext's DI container is not enough to provide me with the correct functionality. Let's say I have a DataService that gets data from a database like this:
public class DataService : IDataService, IDisposable {
public List<MyObject> GetMyObjects()
{
// do something to fetch the data...
return myObjects;
}
}
I can then register this service in the DI container during the configuration phase in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped(typeof(IDataService), typeof(DataService));
}
This ensures the correct lifecylce of the service (one per request scope), however, I need the service to access a different database when a different request is made. For simplicity reasons, let's say the following scenario applies:
when a request to my Web API is made, the DataService will access the currently logged in user, which contains a claim called Database which contains the information which database to use.
the DataService is then instantiated with the correct database connection.
In order to get the second step to work, I have created a constructor for the DataService like this:
public DataService(IHttpContextAccessor accessor)
{
// get the information from HttpContext
var currentUser = accessor.HttpContext.User;
var databaseClaim = currentUser.Claims.SingleOrDefault(c => c.Type.Equals("Database"));
if (databaseClaim != null)
{
var databaseId = databaseClaim.Value;
// and use this information to create the correct database connection
this.database = new Database(databaseId);
}
}
By using the currently logged in user and his claims, I can ensure that my own authentication middleware takes care of providing the necessary information to prevent attackers from trying to access the wrong database.
Of course adding the IDisposable implementation is required to cleanup any database connections (and gets called correctly using the scope lifecycle).
I can then inject the DataService into a controller like this
public MyController : Controller
{
private IDataService dataService;
public MyController(IDataService dataService)
{
this.dataService = dataService;
}
}
This all works fine so far.
My questions now are:
Is there another way to create the instance other than using the constructor of the DataService? Maybe accessing the object the IServiceCollection provides in a different place other than during the configration phase which runs only once? Maybe using my own OWIN middleware?
Is this method really safe? Could two requests made at the same time accidentally end up with the DataServiceintended for the other request and therefore end up giving out the wrong data?
What you have is fine.
Is there another way to create the instance other than using the constructor of the DataService? Maybe accessing the object the IServiceCollection provides in a different place other than during the configration phase which runs only once? Maybe using my own OWIN middleware?
Not really. You can use delegate registration but it's the same problem.
Is this method really safe?
Yes
Could two requests made at the same time accidentally end up with the DataServiceintended for the other request and therefore end up giving out the wrong data?
Nope. The IHttpContextAcessor uses AsyncLocal (http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html) to provide access to the "current" http context.

How can I expand a multi-customer system to handle multiple "identical" controllers

Facts:
I'm using webapi on my application.
My application is a multi-customer application.
Most of my business logic is identical but I do have some differences between some customers.
The example I'll give here is a basic "login" example. I have some more critical places in my system where I need an extra controller(I know that I can perform multiple workarounds with this simple login controller).
Let's assume I have a login controller that looks something like this:
public class LoginController
{
public LoginResponse Post(LoginRequest request)
{
// call ICustomer service to authenticate and return a response
}
}
Now I use IOC for my services. So each customer can typically use a different service and authenticate differently, but what happens when I need to return different data back to the client(per customer)?
I can use ILoginResponse & ILoginRequest and achieve this using IOC, but I still would like to add another LoginController(with the same name so my client's will call api\Login) and gain another level of abstraction.
So my next thought was keep the same controller name and split each customers controller into a different DLLs.
So I would have something like this:
CommonControllers.dll
Customer1Controllers.dll
Customer2Controllers.dll
But how can I do the mapping here?
I'll have an interface that looks like:
public interface ILoginControllerInterface<S,T>
{
S Post(T model);
}
And implementations that look like:
CommonControllers.dll
public class LoginController : ILoginControllerInterface<LoginResponse,LoginRequest>
{
public LoginResponse Post(LoginRequest request)
{
// call ICustomer service to authenticate and return a response
}
}
Customer1Controllers.dll
public class LoginController : ILoginControllerInterface<LoginCusomterResponse,LoginCustomerRequest>
{
public LoginCusomterResponse Post(LoginCustomerRequest request)
{
// call ICustomer service to authenticate and return a response
}
}
But how can I tell my resolver to resolve the "correct" LoginController?
I'm using Unityas my IOC container and my services are registered via configuration.
I'd like a place to register my controllers.
I've overridden the default web-api resolver using my own resolver:
GlobalConfiguration.Configuration.DependencyResolver = resolver;
I'm using my customer resolve to resolve basically everything in my application.
I'm not using a controller factory. Since my resolver resolves my controllers and performs DI for me.
Bottom line:
If I get a request to api/login, how can I resolve the correct controller?
Lets say for customer1 I'd like to get the Customer1Controller.dll version and for customer2 I'd like to get the CommonControllers.dll.
I want this to be via a configuration so I can gain flexibility.
BTW:
If there is a better practice to do these kind of things I'd be more than glad to here about it.
Thanks!!!

Request Dependency Resolution in Web API

50,000ft overview:
Web API (OWIN) hosted by IIS.
In OWIN Middleware I do a bunch of things (API Key validation in order to authenticate a request, create principles, etc...).
I am using Unity as my container. Once I actually get to my controllers, I am injecting a service class which abstracts my repository from my controllers. In the service layer I do things like audit tracking, history logging and the like so that everywhere I inject my service classes, I get the added benefit.
This all works, life is good, yada yada yada.
Until...
I have a custom header value (X-OnBehalfOf) which the caller of the API populates with the user ID that a particular request is being performed by. This is a requirement of the application and its implementation is pretty straight forward.
I can easily retrieve this value from anywhere I have access to the Request (OWIN Middleware, controller, etc...). The problem I am trying to solve however comes in when trying to get that value in my service layer.
Since I am using my container to resolve the instance of the service class, I intitially though the best solution would be to implement something like IHeaderProvider and inject that into the constructor of the service class, but I cannot seem to figure out how to get a reference to the Request in that class since it is out of the pipeline.
I am sure there is an obvious way to do this but I keep running into issues. Does anyone know how to get that reference without having to new it up so that I can leverage my DI container to do the work for me?
It would appear I just needed to put it down on paper. This is how I solved it:
Container:
container.RegisterType<IHeaderProvider, HeaderProvider>(new HierarchicalLifetimeManager());
container.RegisterType<HttpContextBase>(new InjectionFactory(c => new HttpContextWrapper(HttpContext.Current)));
IHeaderProvider:
public interface IHeaderProvider
{
Guid GetOnBehalfOf();
}
HeaderProvider:
public class HeaderProvider : IHeaderProvider
{
private readonly HttpContextBase _httpContextBase;
public HeaderProvider(HttpContextBase httpContextBase)
{
_httpContextBase = httpContextBase;
}
public Guid GetOnBehalfOf()
{
var xOnBehalfOf = _httpContextBase.Request.Headers.Get("X-OnBehalfOfId");
Guid userId;
if (string.IsNullOrWhiteSpace(xOnBehalfOf))
throw new Exception("Missing user ID");
if (Guid.TryParse(xOnBehalfOf, out userId))
{
return userId;
}
throw new Exception("Invalid user ID");
}
}

Asp.net MVC membership design

Some Background to begin:
I've implemented a custom MembershipProvider that validates a user from my service layer called "WebMemberShipProvider"
Currently I have a service called "MembershipService", this service implements the interface IMembershipService on the service layer.
this MemberShipService queries the dal, and validates a user based on username/password
I've also created a custom AuthorizeAttribute named "AuthorizeOwnerAttribute" and this is where I'm having design issues.
For each controller I have a dependency on a Service. eg. UsersController takes a IUserService in it's constructor.
How can I call AuthorizeAttribute on an ActionResult where the current logged in user and the user being edited have the same "StudioId". Note: I want to use AuthorizeAttribute with multiple controllers, not just "UserController"
So my questions to you are:
What should I do to store the
current authenticated user's
"StudioId", as this will be used
across multiple controllers.
How should I pass authentication down to the service layer, because I want to validate that the requests are valid in the service and data access layers, not just on the client. (If this is advisable, I'm just assuming that validation on the client only is enough if I want to re-use the BLL and DAL later on in a stand-alone application)
Technologies used:
- LINQ to SQL via the
Repository pattern
- ASP.NET MVC Preview 2
Any recommendations or code examples would be very welcomed.
I basically did my security mostly at the controller level for something like this. I made a decision not to pass things down too far down the chain in order to find out whether or not a person had access to it or if I did I would just make sure IPrincipal.IsInRole() would be enough to satisfy it.
Now I did something else that feels somewhat hackier. I needed to make sure that people that were registered and had this piece assigned to them were the only ones able to access it from this section.
So I created an attribute filter that works much like this:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var thingToView = filterContext.ActionParameters[_thingToView] as thingToView ;
var registration = filterContext.ActionParameters[_registration] as Registration;
if (!registration.CanSeeThing(thingToView))
{
throw new RegistrationCannotViewThing(registration, thingToView);
}
base.OnActionExecuting(filterContext);
}
Now the thing that felt somewhat hacky in this implementation is that I did this on my controller method:
[AuthFilter(ThingToView ="thingToView", Registration="registration")
public ActionResult Method(Thing thingToView, Registration registration)
{
....
}
The actual parameter assignments occurred in the model binder. The security happens through the filter which checks the parameters passed to the method. I then reused this filter in a lot of places.
I did something similar with a model binder to a Scott Hanselman post here: http://www.hanselman.com/blog/IPrincipalUserModelBinderInASPNETMVCForEasierTesting.aspx in order to pass what user is calling a method.
I suppose you can use the example blog post above in order to get your user object to your controller method in order to pass it to your service layer.

Categories