I'm using EF Core 3.0 and I like to implement a ABAC system to control rights in my app. To do it I'd like to do all the permissions stuff in just one layer and control it using some decorators in the controllers. The idea is to follow a bit this example. I think using the new UseAuthorization method will be also helpful.
I am still designing the solution and I have an issue: currently in my controllers I have functions such as (the AuthorisationFilter is not implemented yet, it's precisely where I'm working on)
// GET api/project/:id
[HttpGet("{projectId}")]
[AuthorisationFilter]
public async Task<ProjectDTO> GetProjectById(int projectId)
{
return await this.projectService.GetProject(projectId);
}
and I also have some others that return all projects:
// GET api/project/projects
[HttpGet("projects")]
[AuthorisationFilter]
public async Task<IEnumerable<ProjectDTO>> GetAllProjects()
{
return await this.projectService.GetAllProjects();
}
Now, in my first case, my authorization filter should simply consider according to some attributes if a certain user is able to access this project or not. Clear.
However, in the second case, it could be that one user can see some projects and a different user can see some different projects, and I don't know exactly what my authorisation filter should return. Allow or deny? If I deny, I lose control of what happens next.
I understand the authorisation filter is not the place to create the conditions to generate the SQL query, but I don't like either to simply accept the action and lose control of the permissions. In other words: if there is a bug in the implementation of GetAllProjects which returns more projects than the authoirised ones, I should not send these projects to the user.
Hence: how should the authorisation layer work? Should I filter there the valid projectId's and then call GetAllProjects with this list as an argument?
In a nutshell: is there a way put all the rights control in a single layer?
Authorization layer should provide details about what the user can do, but enforcing that is up to the individual components.
Your ProjectService need to know what the user is authorized to do and enforce it.
If your authorization layer decides that, it can become very involved in pretty much everything your application does, as it need to know way too much about each controller action or the database access, or whatever else which will not be very maintainable.
What if one of your services decides to access a 3rd party service over a 3rd party SDK?, it would make sense for your ..say MyTwitterService to enforce that rather than a generic authorization layer.
Usually you pass in the context of the user (usually some sort of "rights" the user has) and the ProjectService will decide what things to return. (or fail if the rights are insufficient or invalid).
We have a multi-tenant web application in which a many pages operate per-tenant. As a result many of our interfaces look like this
interface ISprocketDeployer
{
void DeploySprocket(int tenantId);
}
It occurred to me that it might be better to simplify these interfaces to be unaware of the tenantId. The pages would also then be unaware of the tenantId, like so
[Inject] // Ninject
public ISprocketDeployer SprocketDeployer { get; set; }
private void _button_OnClick(object sender, EventArgs e)
{
SprocketDeployer.DeploySprocket();
}
The dependency injection framework would then inject the tenant ID as a dependency by looking at the currently authenticated user. Is this a good idea or just an abuse of dependency injection?
It further occurred to me that many implementations also take additional dependencies just for looking up details about the tenant, and that I could reduce the number of dependencies further by just injecting in that detail directly, for example
class SprocketDeployer
{
public SprocketDeployer(ITenantRepository tenantRepository)
{
_tenantRepository = tenantRepository;
}
void DeploySprocket(int tenantId)
{
var tenantName = _tenantRepository.GetTenant(tenantId).Name;
// Do stuff with tenantName
}
}
Would become
class SprocketDeployer
{
public SprocketDeployer(Tenant tenant)
{
_tenant = tenant;
}
void DeploySprocket()
{
var tenantName = _tenant.Name;
// Do stuff with tenantName
}
}
I then realised that I could also inject in other "dependencies", such as details about the currently logged in user in the same way.
At that point I become unsure. While it seemed like a fantastic idea at first I realised that I wasn't sure when to stop adding extra "dependencies". How do I decide what should be a dependency and what should be a parameter?
I would stop short of calling it abuse, but that said:
The general use case of dependency injection (via a container) is to inject pure services that do not directly represent state. One of the immediate problems is informing the container of which instance of your object it should be injecting at run-time. If your SprocketDeployer requires a Tenant, and your system includes many Tenants, how does the container figure out which tenant to supply at runtime?
If you want to avoid passing Tenant around, consider using Thread Local Storage (TLS). However, there will still be some point in the pipeline where the Tenant needs to be added to TLS.
Edit
From your comment:
I solve the problem of figuring out which tenant to supply at runtime
in Ninject by binding the type to a method which examines
HttpContext.Current and using InRequestScope. It works fine, but I've
not seen anything to indicate that this is (or isn't) a recommended
practice.
If I understand you correctly, that sounds like a factory of sorts? If that's the case, I see nothing wrong with it.
A minor nitpick might be: it's nice to be able to not have to be concerned about how your services are scoped. When they are truly stateless services, you can view them as pure swappable components that have no side effects based on container configuration.
As with Phil, I would not call this dependency injection abuse, though it does feel a bit odd.
You have at least a few options. I'll detail a couple that seem the best from the detail you've provided, though these may have been what you were referring to when you said 'I then realised that I could also inject in other "dependencies", such as details about the currently logged in user in the same way.'
Option 1: Abstract tenant identification to a factory
It may make perfect sense to have an abstraction that represents the current tenant. This abstraction is a factory, but I prefer the term "provider" because factory connotes creation whereas a provider may simply retrieve an existing object (Note: I realize Microsoft introduced a provider pattern but that's not what I'm referring to). In this context you're not injecting data, instead you're injecting a service. I'd probably call it ICurrentTenantProvider. The implementation is frequently context specific. Right now, for example, it would come from your HttpContext object. But, you could decide a specific customer needed their own server and then inject an ICurrentTenantProvider that would retrieve it from your web.config file.
Option 2: Hide multitenancy entirely
Unless you ever have to do different things based on the tenant[1], it may be better to hide the multitenancy entirely. In this case you'd inject classes, that I'm going to call providers, that are context aware and the result of whose function calls would be based on the current tenant. For example, you might have an ICssProvider and an IImageProvider. These providers alone would be aware that the application supported multitenancy. They may use another abstraction such as the ICurrentTenantProvider referenced above or may use the HttpContxt directly. Regardless of the implementation, they would return context specific to the tenant.
In both cases, I'd recommend injecting a service instead of data. The service provides an abstraction layer and allows you to inject an implementation that's appropriately context aware.
Making the Decision
How do I decide what should be a dependency and what should be a parameter?
I generally only ever inject services and avoid injecting things like value objects. To decide you might ask yourself some questions:
Would it make sense to register this object type (e.g., int tenantId) in the IoC container?
Is this object/type consistent for the standard lifetime of the application (e.g., instance per http request), or does it change?
Will most objects end up dependent on this particular object/type?
Would this object need to be passed around a lot if made a parameter?
For (1), it doesn't make sense to inject value objects. For (2), if it is consistent, as the tenant would be, it may be better to inject a service that's aware of the tenant. If yes to (3), it may indicate a missing abstraction. If yes to (4) you may again be missing an abstraction.
In the vein of (3) and (4) and depending on the details of the application, I could see ICurrentTenantProvider being injected in a lot of places, which may indicate it's a little low level. At that point the ICssProvider or similar abstractions may be useful.
[1] - If you inject data, like an int, you're forced to query and you may end up in a situation where you'd want to replace conditional with polymorphism.
10/14/15 UPDATE BEGIN
A little over three months later I've had a bit of a change of heart on the specific situation I mentioned running into with this approach.
I had mentioned that for a long time now I've also regularly injected the current "identity" (tenantAccount, user, etc.) wherever it was necessary. But, that I had ran into a situation where I needed the ability to temporarily change that identity for just a portion of the code to be executed (within the same execution thread).
Initially, a clean solution to this situation wasn't obvious to me.
I'm glad to say that in the end I did eventually come up with a viable solution - and it has been happily churning away for some time now.
It will take some time to put together an actual code sample (it's currently implemented in a proprietary system) but in the meantime here is at least a high level conceptual overview.
Note: Name the interfaces, classes, methods, etc. whatever you like - even combine things if that makes sense for you. It's just the overall concepts that are important.
First, we define an IIdentityService, exposing a GetIdenity(). This becomes the de facto dependency for getting the current identity anywhere we need it (repos, services, etc. everything uses this).
The IIdentityService implementation takes a dependency on an IIdentityServiceOrchestrator.
In my system the IIdentityServiceOrchestrator implmentation makes use mutliple IIdentityResolvers (of which only two are actually applicable to this discussion: authenticatedIdentityResolver, and manualIdentityResolver). IIdentityServiceOrchestrator exposes a .Mode property to set the active IIdentityResolver (by default this is set to 'authenticated' in my system).
Now, you could just stop there and inject the IIdentityServiceOrchestrator anywhere you needed to set the identity. But, then you'd be responsible for managing the entire process of setting and rolling back the temporary identity (setting the mode, and also backing up and restoring the identity details if it was already in manual mode, etc.).
So, the next step is to introduce an IIdentityServiceOchestratorTemporaryModeSwitcher. Yes, I know the name is long - Name it what you want. ;) This exposes two methods: SetTemporaryIdentity() and Rollback(). SetTemporaryIdentiy() is overloaded so you can set via mode or manual identity. The implementation takes a dependency on the IIdentityServiceOrchestrator and manages all the details of backing up the current existing identity details, setting the new mode/details, and rolling back the details.
Now, again you could just stop there and inject IIdentityServiceOchestratorTemporaryModeSwitcher anywhere you'd need to set the temporary identity. But, then you'd be forced to .SetTemporaryIdentity() in one place and .Rollback() in another and in practice this can get messy if it's not necessary.
So, now we finally introduce the final pieces of the puzzle: TemporaryIdentityContext and ITemporaryIdentityContextFactory.
TemporaryIdentityContext Implements IDisposable and takes a dependency on both the IIdentityServiceOchestratorTemporaryModeSwitcher and an Identity / Mode set via an overloaded constructor. In the ctor we use the IIdentityServiceOchestratorTemporaryModeSwitcher.SetTemporaryIdentity() to set the temporary identity and on dispose we call into IIdentityServiceOchestratorTemporaryModeSwitcher.Rollback to clean things up.
Now, where we need to set the identity we inject the ITemporaryIdentityContextFactory which exposes a .Create() (again overloaded for identity / mode) and this is how we procure our temporary identity contexts. The returned temporaryIdentityContext object itself isn't really touched it just exists to control the lifetime of the temporary identity.
Example flow:
// Original Identity
Using (_TemporaryIdentityContextFactory.Create(manualIdentity)) {
// Temp Identity Now in place
DoSomeStuff();
}
// Back to original Identity again..
That's pretty much it conceptually; obviously a LOT of the details have been left out.
There's also the matter of IOC lifetime that should be discussed. In its purest form as discussed here, generally each of the componenets (IIdentityService, IIdentityServiceOrchestrator, ITemporaryIdentityContextFactory) could be set to a 'PerRequest' lifetime. However, it could get funky if you happen to be spawing multiple threads from a single request... in which case you'd likely want to go with a 'perthread', etc. lifetime to ensure there was no thread crosstalk on the injections.
Ok, hope that actually helps someone (and didn't come across as completely convoluted, lol). I'll post a code sample that should clear things up further as I have time.
10/14/15 UPDATE END
Just wanted to chime in and say you're not alone in this practice. I've got a couple multi-tenant apps in the wild that inject the tenant information where it's needed in the same manner.
However, I have more recently ran into an issue where doing this has caused me quite a bit of grief.
Just for the sake of example lets say you have the following (very linear) dependency graph:
ISomeService -> IDep2 -> IDep3 -> ISomeRepository -> ITenentInfoProvider
So, ISomeService depends IDep2, which depenends on IDep3... so on and so on until way out in some leaf ITenentInfoProvider is injected.
So, what's the problem? Well, what if in ISomeService you need to act on another tenant than the one you're currently logged in as? How do you get a different set of TenantInfo injected into ISomeRepository?
Well, some IOC containers DO have context-based conditional support (Ninject's "WhenInjectedInto", "WhenAnyAnchestorNamed" bindings for example). So, in simpler cases you could manage something hacky with those.
But what if in ISomeService you need to initiate two operations, each against a different tenant? The above solutions will fail without the introduction of multiple marker interfaces, etc. Changing your code to this extent for the sake of dependency injection just smells bad on multiple levels.
Now, I did come up with a container based solution, but I don't like it.
You can introduce an ITenantInfoResolverStratagy and have an implementation for each "way" of resolving the TenantInfo (AuthenticationBasedTenantInfoResolverStratagy, UserProvidedTenantInfoResolverStratagy, etc.).
Next you introduce a CurrentTenantInfoResolverStratagy (registered with the container as PerRequestLifeTime so it's a singlton for the life of your call, etc.). This can be injected anywhere you need to set the strategy that will be used by downstream clients. So, in our example we inject it into ISomeService, we set the strategy to "UserProvided" (feeding it a TenantId, etc.) and now, down the chain, when ISomeRepository asks ITenentInfoProvider for the TenantInfo, ITenentInfoProvider turns around gets it from an injected CurrentTenantInfoResolverStratagy.
Back in ISomeService, the CurrentTenantInfoResolverStratagy could be changed multiple times as needed.
So, why don't I like this?
To me, this is really just an overly complicated global variable. And in my mind just about all the problems associated globals apply here (unexpected behavior due to it being mutable by anyone at any time, concurrency issues, etc. etc. etc.).
The problem this whole thing sets out to solve (mostly just not having to pass the tenantId / tenantInfo around as a parameter) is probably just not worth the inherent issues that come with it.
So what's a better solution? Well there probably is some elegant thing that I'm just not thinking of (maybe some Chain Of Command implemenation?).
But, really I don't know.
It may not be elegant but passing a TenantId / TenantInfo around as a parameter in any tenant related method calls would definitely avoid this whole debacle.
If anyone else has better ideas please by all means chime in.
I'm trying to figure out the correct way to implement and code the following using desing patterns, or a good object oriented solution:
There is an user class which can contains a variable set of permits, each one enables him to do different action on the application. The idea is to be able tell a certain user object to, for example delete an order, if he has any permits that enable him to do so, do it and if not, to raise an exception.
If someone has a place where to read about this, it's helpfull too.
thanks
There are built in functions for permission in C#/.NET.
The access requirements on a function is set through the PrincipalPermissionAttribute class, or inside the code with PrincipalPermission. To prevent a method from being called unless the current user is a member of the Administrators role, the following attribute is used (sample from MSDN):
[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
static void CheckAdministrator()
{
Console.WriteLine("User is an administrator");
}
Both these checks against the current identity of the calling thread. So what you need to do is to implement the IPrincipal interface to allow your users to be set as the thread identity. Then you can use standard .NET PrincipalPermission to check security. It works exactly as you want - if the security demand is not met, an exception is thrown.
If one user can have multiple permits, each permit allows different execution tasks, then you might wanna have a look at decorator pattern.
although it depends a lot on your requirements.
I am building a web site in C# using asp.NET MVC
How can I secure that no unauthorized persons can access my methods?
What I mean is that I want to make sure that only admins can create articles on my page. If I put this logic in the method actually adding this to the database, wouldn't I have business logic in my data layer?
Is it a good practise to have a seperate security layer that is always in between of the data layer and the business layer to make?
The problem is that if I protect at a higher level I will have to have checks on many places and it is more likely that I miss one place and users can bypass security.
Thanks!
Authorize filters (as pmarflee said) are sort of the canonical example of how to secure your controllers, though that doesn't always satisfy your requirements (e.g. if you're exposing your model through other means such as if you're also exposing a WCF service).
The more global and flexible means is to require a security service somewhere (your choice where, but commonly in either the controller or repository base) and then pass in a user context somehow (either through params or constructor). yes, that means you have to be sure to call that service in each action, but it's pretty hard to avoid that unless you decide to go with some sort of aspect-oriented programming container.
Have a look at this post, which explains how to use action filters to provide authorization on controller actions.
For your problem there are Policy base authorization: https://learn.microsoft.com/en-US/aspnet/core/security/authorization/policies?view=aspnetcore-6.0
some time ago we implemented impersonation into our application (a DMS system). We did this because the users should not have access to the physical files of the document pages.
So the user logs into our application, gets impersonated to a special user so he can access the files he needs from within our application.
When this impersonation was planned we didn't think that it would be a great thing: The user impersonates one time and everything is fine. We implemented the code into the existing methods where it was needed (just sth. like Impersonation=true or Impersonation=false).
This was wrong: Impersonation had to set off and on on several places (for example, when the user wants to send a document as an email you have to set impersonation off to use the user's mail profile) so whenever we add a new functionality we have to test with and without impersonation.
Because I have additional functionality to implement I would like to extinct this behaviour to get a clean approach. But I don't really have an idea what could be best approach.
First thing that comes into my mind would be the state pattern, but this would result in an impersonated class and a not-impersonated class for all classes where impersonation takes effect. This would increase the number of classes.
Other thing would be method pointers: When using impersonation call impersonated version of function, else call not-impersonated version of function.
This would lead to more methods. Better than state pattern approach? I don't think so.
So, what would be your approach to get a clean solution?
(I already thought about using threads but this seems to be very complicated)
Hope you can help me.
Regards,
inno
Sounds like a crosscutting aspect - maybe aspect oriented programming?
Well one option would be to define what the default behavior should be such as impersonation on for the user. This default behavior would happen at time of login to the system. When the user performs other behaviors in the system such as sending a document as email this could be encapsulated in a service where the service takes the user as an argument and then uses the impersonation necessary for that feature. To take your example:
var emailService = new emailService();
//inside the service call it would apply the impersonation necessary for the operation
emailService.send(user, new Attachment(documentToSendViaEmail));