Authorization in a more purely OOP style - c#

I've never seen this done but I had an idea of doing authorization in a more purely OO way. For each method that requires authorization we associate a delegate. During initialization of the class we wire up the delegates so that they point to the appropriate method (based on the user's rights). For example:
class User
{
private deleteMemberDelegate deleteMember;
public StatusMessage DeleteMember(Member member)
{
if(deleteMember != null) //in practice every delegate will point to some method, even if it's an innocuous one that just reports 'Access Denied'
{
deleteMember(member);
}
}
//other methods defined similarly...
User(string name, string password) //cstor.
{
//wire up delegates based on user's rights.
//Thus we handle authentication and authorization in the same method.
}
}
This way the client code never has to explictly check whether or not a user is in a role, it just calls the method. Of course each method should return a status message so that we know if and why it failed.
Thoughts?

This is basically the null object pattern for authorization. It's an interesting idea if you can figure out a way to design StatusMessage such that the calling code doesn't need special cases. For instance, for certain actions, you'll want to indicate "You can't do that as a guest, but would you like to login or sign up for an account?" So certain StatusMessages might need to redirect to a login/sign up page.

Related

ASP.NET MVC5 - Override OnAuthorization() - 'MvcResources' is inaccessible due to its protection level

The main goal: I am creating a website (ASP.NET MVC 5) where I need to add some additional Authorization and redirection logic: For example, a user can only view page C after completing pages A and B. If they have completed page A and not B, and try to access page C, they will be redirected to page B.
After a good amount of research, my plan is to create a custom AuthorizationAttribute , and override OnAuthorization(). I want to do this responsibly, so I looked at the [source code][1] for this method, and want to only add logic to it, not take it away. I've started by copying that code over to my own subclass (which I include at the end of this post):
The problem is there are two elements here that I apparently cannot access:
MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache
CacheValidateHandler
The first is in System.Web.Mvc.Properties , and the error I get is that 'MvcResources is inaccessible due to its protection level'. All of the help I've seen online regarding this advises that the programmer change the access modifier for their class, but I can't since I didn't write this class: it's system code.
The second (CacheValidateHandler) 'does not exist in the current context'. It's a method in my parent class (AuthorizeAttribute), but it's private.
So is there something I'm missing? Does my subclass have to be in a special location (right now it's in a folder called Helpers) or do I have to do something different with namespaces? I'm still pretty new to C#. How can I safely override OnAuthorize if I'm not even able to repeat what the parent method does?
namespace MyApp.Helpers
{
public class MyAppAuth : AuthorizeAttribute
{
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
// If a child action cache block is active, we need to fail immediately, even if authorization
// would have succeeded. The reason is that there's no way to hook a callback to rerun
// authorization before the fragment is served from the cache, so we can't guarantee that this
// filter will be re-run on subsequent requests.
throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
}
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);
if (skipAuthorization)
{
return;
}
if (AuthorizeCore(filterContext.HttpContext))
{
// ** IMPORTANT **
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{
HandleUnauthorizedRequest(filterContext);
}
}
}
}
I believe I have a solution, but I would really love if someone with more experience could comment if what I'm doing is in any way unsafe.
For the first issue, I simply replaced MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache with a string, since this is one of the possible overloads of InvalidOperationException.
For the second issue, I copy-pasted the parent's private CacheValidateHandler() method:
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}

Best practise for optional injecting of current user

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 :)

Controlling access to methods

Is there a way to control access to methods to certain roles in .net. Like
class A
{
//should only be called by Admins**
public void Method1() { }
//should only be called by Admins and PM's**
public void Method2() { }
}
I'm using windows authentication only for retrieving user names and nothing more.User roles are maintained in a different application. I think it's possible through attributes but I'm not really sure how
It it possible, I have used it on an web project that used asp.net and AzMan as the authentication.
Take a look at Code Access Security
From memory all of our methods looked something like
[Permission(SecurityAction.Demand, "Permission")]
public void Method1
It's been a while though so that might not be actually 100% correct.
I'd also highly suggest if you are going to put protection down to this level to look at a task orientated permission approach as this is much more flexible than role based permissions
You can do this as follows:
class A
{
//should only be called by Admins**
[PrincipalPermission(SecurityAction.Demand, Role="Admin")]
public void Method1()
{
}
//should only be called by Admins and PM's**
[PrincipalPermission(SecurityAction.Demand, Role="Admin")]
[PrincipalPermission(SecurityAction.Demand, Role="PM")]
public void Method2()
{
}
}
To do this Thread.CurrentPrincipal must be set to a principal that has the required roles. For example, if you enable roleManager in an ASP.NET application, Thread.CurrentPrincipal will be set to a RolePrincipal with roles from your configured RoleProvider. See this MSDN article for more info.
You can do it using custom validation.
1- Make a method in another public class which take login id as parameter and return roles in form of bits.
2- Call this method on the page_Load event of the required class and save returned bits in the view state.
3- Now validate required method on the basis of roles bits.

What's the most elegant way to verify access rights on a method (C#.Net)

I have a WebService built in WCF (C#.Net) that contains dozens of methods. On every methods, I wan't to validate if the current user has access to this particular action.
Right now, I have something like this :
public MyContract MyMethod(int MyParameter)
{
ValidateAccess(MyCurrentIdentityInfo, ActionEnum);
// Do stuff here...
}
public void MyMethod2(int MyParameter)
{
ValidateAccess(MyCurrentIdentityInfo, ActionEnum);
// Do stuff here...
}
etc...
You'll notice that I call a method at the beginning to check the access rights and then, do the code I need. This code works fine, but I have to call this method on every method in my service and I don't find it pretty.
Is there a more elegant way to acheive what I'm trying to do? I tried using a custom attribute but didn't succeed.
Note that I'm NOT trying to authenticate the user on the WebService itself. In the exemple above, the user would be valid on the WebService. But I'd like to run a custom code to check if he can call a method that deletes a record for instance.
You can think to use Castle Dynamic Proxy to inject the validation of the operation on the logged user.

Authorising Web App users against User Information as well as Role

I was wondering if anyone would be able to help me with the following?
I need some more complicated rules for authorisation in a webapp than just role, which I have working fine. Something along the lines of "Allow all Admins. Allow Buyers, provided they have the correct department ID and are allowed to see this customer's credentials".
I am using a custom identity and custom principal to store information such as whether a user is allowed to see all clients or which individual clients they may see. This information is retrieved from a database and added upon creation of the identity/principal.
I have created a custom permission that extends IPermission, ISecurityEncodable. Within this, I have modified the Demand() function to the following:
public void Demand()
{
this._identity = (UserIdentity)Thread.CurrentPrincipal.Identity;
if (Thread.CurrentPrincipal.IsInRole("Admin")) { }
else if ((Thread.CurrentPrincipal.IsInRole("Buyer")) &&
(this._identity.CanViewAllClients) &&
(this._identity.IsInDept(this._departmentID)) ) { }
else if ((Thread.CurrentPrincipal.IsInRole("Buyer")) &&
(this._identity.CanViewClient(this._requestedClient)) &&
(this._identity.IsInDept(this._departmentID)) ) { }
else { throw new SecurityException("Custom Permission Denied"); }
}
I then call this when I wish to authorise by using
CustomPermission custperm = new CustomPermission(requestedClient, reqClientDept);
custperm.Demand();
This works fine, but seems a messy, hacky way to do things. Especially since it would be nice to use my security roles as an attribute e.g.
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class...
Perhaps there is a way to call [CustomPrincipalPermission(SecurityAction.Demand, Authorised = true)] with a custom IsAuthorised check? Is this possible? What would need to be implemented?
I apologise if there is a simple solution that I've missed online, but rest assured I have been checking for days now.
It seems like what you want is a declarative rather than a programmatic demand. In order to do so, you'll need to create a CustomPermissionAttribute based on your CustomPermission.
There's an example of a declarative demand of a custom permission here and details of creating a custom permission attribute here.

Categories