I am extending the AuthorizeAttribute to create my own custom AuthorizeUser filter. I override the:
AuthorizeCore(HttpContextBase httpContext) method, to perform my database check manually and return the proper boolean. This works fine but I am looking into examples with Principle and Identity, and I am very confused on when doing something like,
[Authorize(Roles = "admin")]
without overriding the AuthorizeCore method, what is actually happening.
Behind the scenes, where does it get the user's current list of roles to compare to? How is that assigned? I see AuthorizeAttribute has a Roles member, but this is where I am stuck, understanding what it is comparing the passed in values to.
Also, overriding the AuthorizeCore, and grabbing the user roles, and comparing them myself is there any security risks?
Related
I am having some trouble with Authorization policies. I have a baseWebApiController with an action
[HttpDelete("{id}"), Authorize(Policy = "Administrator")]
public virtual async Task<IActionResult> Delete(int id) {}
But in a certain controller which inherits from the above I want to give access to users also, with a policy like:
[HttpDelete("{id}"), Authorize(Policy = "All")]
public override Task<IActionResult> Delete(int id){}
It seems regular users cannot access this action. Do I have to search further for errors in my policy configuration, or since the controller is inherited,m it's attributes are neglected?
Thanks
The AuthorizeAttribute is an attribute that is inherited and that allows itself to be applied multiple times.
That means when inheriting your method which already has an AuthorizeAttribute, that will be carried over. So the final function definition in your subclass would look like this:
[Authorize(Policy = "Administrator")]
[Authorize(Policy = "All")]
public override Task<IActionResult> Delete(int id)
So the route now has two policies in place. This is kind of a problem because policies are designed to be cumulative. So all policies have to pass in order for the authentication to succeed.
Of course, this will not work for you because you actually wanted to “wash out” the original policy from the base class. This is not possible though, so you would have to remove the policy from the base class and maybe introduce a second administrator-only class for those policies.
The general problem here is that your policy design seems to be based on roles. You are using policies, but effectively, you are checking on roles there. Instead, you should consider working with requirements: For example, to delete something, a user would need to fulfill the “DeletionAllowed” requirement. This allows for a much more fine-grained policy system. And the big benefit? Requirement handlers are disjunctive: So one handler that is able to fulfill the requirement is enough to pass it.
I've started looking into ASP.NET core, in particular Authorization. The model's changed quite a bit and I must say I'm finding it a little confusing compared to the last implementation.
I've seen various posts lamenting that it's now not possible to pass parameters to the Authorization attribute constructor and that instead we now have Policy/Requirement/Handler.
So what exactly is the user case for AuthorizeFilter? How does it differ from AuthorizeAttribute? When should I implement Requirement/Handler and when (or should I ever) implement an AuthorizeFilter (which looks like it might work closer to the old model)?
I couldn't find any resources online that detailed this particular aspect so any enlightenment is greatly appreciated.
The Documentation above the class of AuthorizeFilter says:
MVC recognizes the <see cref="T:Microsoft.AspNetCore.Authorization.AuthorizeAttribute" />
and adds an instance of this filter to the associated action or controller.
So when a controller is created an instance of the AuthorizeFilter is added to the controllers filters when a AuthorizeAttribute is present.
Basically they split the decoration: AuthorizeAttribute from the implementation: AuthorizeFilter.
So if you want clean code you can use AuthorizeAttribute to decorate your controller class.
if you want more understandable/logical code you can add te AuthorizeFilter to the filters in the Controller Constructor method.
I'm upgrading from v3 to v4 of MvcSiteMap, and it seems just using the property Html.MvcSiteMap().SiteMap.CurrentNode.HasChildNodes triggers a hit on HandleUnauthorizedRequest in AuthorizeAttribute for every unathorized child node in the list.
Why should this happen? I would expect HandleUnauthorizedRequest to be triggered for a separate http request, not just interrogating whether a node exists.
What is the best way to distinguish between a 'genuine' unauthorized http request and simply checking an unauthorized sitemap node? My best guess so far is to check whether the controller and action match, but it seems a little unnecessary:
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
var httpRouteData = ((MvcHandler)filterContext.HttpContext.CurrentHandler).RequestContext.RouteData;
var filterRouteData = filterContext.RequestContext.RouteData;
var isHttpRequestUnauth = (httpRouteData.Values["Controller"] == filterRouteData.Values["Controller"] &&
httpRouteData.Values["Action"] == filterRouteData.Values["Action"]);
if (isHttpRequestUnauth)
throw new System.Web.HttpException(403, string.Format("Access denied for path '{0}'. ", filterContext.HttpContext.Request.RawUrl));
else
base.HandleUnauthorizedRequest(filterContext);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
HandleUnauthorizedRequest is only called by the MVC AuthorizeAttribute in the case where the authorization check fails. It is meant only for setting the handler of the request, not actually to provide the check whether the user is authorized. That said, MvcSiteMapProvider doesn't call HandleUnauthorizedRequest directly - it calls OnAuthorization.
The default implementation of AuthorizeAttribute.OnAuthorization makes the check already, so I am unsure what you hope to accomplish by comparing the controller and action again in HandleUnauthorizedRequest since unauthorized users cannot reach that path unless you override the implementation of OnAuthorization as well (or you rely on output caching entirely).
Anyway, to answer your question, in v3 and early revisions of v4 MvcSiteMapProvider used Reflection.Emit to generate a class on the fly that inherited from AuthorizeAttribute or any subclass of AuthorizeAttribute as described in this post. The subclass added public access to the AuthorizeCore method so it could be called by MvcSiteMapProvider. However, that approach had performance issues and also could not be used with sealed overloads of AuthorizeAttribute.
Since then, it has evolved to use the one and only public member of AuthorizeAttribute - OnAuthorization - to do the check. The author of the above post made an error in his assertion that Reflection.Emit was the only way it could be done because he didn't take into account using a subclass of HttpContext.Response that overrides the output caching members. We compromised on using the result of HandleUnauthorizedAttribute (setting the filterContext.Result property to a non-null value) as the way to determine whether or not the security check works.
Unfortunately, there is not a way to make a solution that works 100% of the time because AuthorizeAttribute was only designed to be used in the context of a request for the current page, but this is the solution that we compromised on because it requires the least amount of code to maintain, performs the best, and uses direct method calls instead of workarounds. If you use the typical method of overloading AuthorizeCore for custom logic, it will work perfectly. On the other hand, if you overload OnAuthorization or HandleUnauthorizedRequest, you need to ensure that the filterRequest.Result property is set to non-null for unauthorized and null for authorized.
I am creating a role in Simplemembership like so:
Roles.CreateRole("Admin")
It works fine, however I have seen people instantiate and then call the CreateRole method like so:
var roles = (SimpleRoleProvider)System.Web.Security.Roles.Provider;
roles.CreateRole("Admin")
So this is effectively like saying:
Roles.Provider.CreateRole("Admin")
My question is, is the way I am doing it OK as I am using the system.web.security.roles class without instantiating it. Thanks
It's not instantiation. It's just a cast to local variable:
var roles = (SimpleRoleProvider)System.Web.Security.Roles.Provider;
There is no any difference between these two approaches. They are the same.
The only advantage can be if your CustomRoleProvider will have some extra method, that you want to call, then you need to cast it.
Instantiation in that case would be:
var roles = new SimpleRoleProvider();
But in case of RoleProvider mechanisms it makes no sense, as it won't use Role providers collection
When calling the method CreateRole there is no difference because it is available in both the Roles and SimpleRoleProvider classes. The difference in these two classes is in the methods and properties available. Compare the Roles class definition to
the definition of SimpleRoleProvider. For example, Roles does not have a property UserIdColumn whereas SimpleRoleProvider does, because it is specific to the SimpleMebmership implementation and can be useful. Since SimpleRoleProvider is the actual provider configured for SimpleMembership it is safer to cast it to that provider. If you call a method in Roles that is not implemented in SimpleRoleProvider it will throw a not implemented exception. By casting to SimpleRoleProvider you can see what properties and methods are actually available to the provider with IntelaSense.
I have created ASP.net MVC4 application with Internet application template,
and want to add List<T> property to MembershipUser object provided by ASP builtin Forms Authetication.
This List property will be a list of StockPermission object:
public class StockPermission
{
private Stock stock;
private byte afterSaveAction;
private bool allowEditingStockDocs;
private bool allowChangingUser;
}
Therefore my MembershipUser will contain StockPermission objects
which let MembershipUser to perform defined action with those Stocks in the List
Before you start trying to do something like this, it would be wise for you to read up on exactly what these systems are. It's clear from your comments that you don't really understand them because you're confusing multiple systems.
FormsAUthentication has nothing to do with MembershipUser. FormsAuthentication is only about providing a cookie for each web request to be shown as authenticated. FormsAuthentication can be used with any kind of credential system.
MembershipUser is part of the Membership subsystem. Membership has nothing to do with FormsAuthentication, other than your code will call into Membership to validate the users credentials, then your code will create a cookie using FormsAuthentication to log the user in.
The changes you want to make are related to permissions, and permissions are not part of the Membership system, they are part of the Role system. These systems are separate for a reason, because they can be replaced with custom implementations. and they have logically different functionality.
Finally, you can't change the MembershipUser, as it's part of the basic framework. You could extend it by deriving your own class from MembershipUser, but that's not the recommended way to do things. You should, instead, have your own User class which references the MembershipUser.ProviderUserId.
In short, you're about to dig into the internals of the framework. This is not something you should do without understanding more about what this is.
To add List property to our MembershipUser object or any other properties we can create custom MembershipProvider and custom MembershipUser classes describer in this article:
http://msdn.microsoft.com/en-us/library/ms366730(v=vs.100).aspx