Why is it bad practice to secure MVC routes? - c#

The MSDN is pretty clear about MVC Routing and Security:
The only supported way to secure an MVC application is to apply the AuthorizeAttribute attribute to each controller and use the AllowAnonymousAttribute attribute on the login and register actions.
However, I am considering the following approach:
First, I have implemented a custom Controller Factory that performs security checks based on information coming from our custom STS.
Among other information, the token issued by the STS contains claims describing all the MVC routes the user is allowed to access.
Then I check the user claims within the CreateController method:
public class SecuredControllerFactory : IControllerFactory
{
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
...
bool isAuthorized = principal.HasRequiredRight(verb, ressource);
...
}
}
This way we can configure and update security rules in a centralized manner, without redeploying our applications. Moreover, it fits the "convention over configuration" idea.
Is there something wrong with this approach? I don't see why it is considered a bad practice? Can someone exhibit a concrete security issue with this?

I guess it is bad practise because it breaks the Single Responsibility principle within the controller factory. The single responsibility of the controller factory should be to select and instantiate controllers.
I would question your reason for going with the controller factory approach:
This way we can configure and update security rules in a centralized
manner, without redeploying our applications.
This is a valid statement if you use the standard AuthorizeAttribute that specifies the allowed users/roles in code.
However, the recommended approach would be to derive from AuthorizeAttribute and implement your security rule logic in the derived class by overriding the protected AuthorizeCore() method. For example, it could look up permissions in a database so you could change them dynamically at runtime.
This also allows you to implement custom logic that gets called when the authorization check fails (HandleUnauthorizedrequest() method), which is presumably what you have to do in your custom controller factory when the authorization logic fails (e.g. redirect to a sign-on or error page?)
That way, you get the ability to change your security rules and manage them centrally without redeploying the whole application and you don't break the single responsibility of the ControllerFactory
ThinkTexture provide a good implementation in their identity model framework, as described here
http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/
This allows you to specify a Resource/Action and to encapsulate the authorization logic in a custom ClaimsAuthorizationManager in the usual WIF way. If you don't specify the resource and action explicitly in the attribute, the framework gets the values from the using the current HttpActionContext, which is nice.

Related

.NET OAuthAuthorizationServerProvider Multiple Login Routes

Currently we have a class that extends OAuthAuthorizationServerProvider which is used for web routes. We are adding a separate API, in which case we still want to use that OAuthAuthorizationServerProvider class.
How is it possible to register two different login routes, and how can we distinguish between those two routes inside our OAuthAuthorizationServerProvider child class?
EDIT: I think I could compare the path via context.Request.Path.
I need to perform some logic in the GrantResourceOwnerCredentials method that will share some logic across the two logins, but some of the logic needs to be different.
We ended up using the same login route, but for our app we used resource owner credentials (grant type password) and for the API we used client credentials (grant type client_credentials).

ASP.NET: What is the purpose of IAuthorizationService

I am trying to understand the ASP.NET policy-based authorization mechanism, and I understood that I need to do the following:
Set up a policy
Assign requirements to that policy
Define authorization handlers to these requirements which perform the actual validation (And return whether the requirements were fullfilled or not)
Add the authorization handlers to the dependency injection mechanism
However, reading the ASP.NET documentation, I understand I might need to set up an IAuthorizationService as well. I failed to understand why that is needed for from the ASP.NET documentation.
Do I have to set one up? What should it do? Is that an alternative to the policy and authorization handlers I am setting up or a required addition to them?
U can override IAuthorizationService to take control of full authorization logic in your application.
By default, IAuthorizationService is responsible for validation of Policy- Claim- or Role-based ruled, defined in AuthorizationOptions.
IAuthorizationService is usually being invoked in IAsyncAuthorizationFilter (which MVC adds automatically once u mark Controller or Action with [Authorize] attribute).

Enabling specific authentication/authorization schemes on a per-endpoint basis

ASP.NET has the [Allow Anonymous] attribute which allows you to bypass authorization on a specific endpoint. I'm wondering if there's a common way of enabling specific authentication schemes on an endpoint by endpoint basis.
Imagine you wanted to support different schemes like a Basic scheme and a Bearer scheme and so on. But you didn't want to support all schemes on all endpoints. It seems like a convenient way to do that would be to create attributes like [BasicAuth] and [BearerAuth] so you could just annotate the specific endpoints you want to enable. Looking at how AuhtorizationAttributes work, however, it seems like they behave like a logical AND rather than a logical OR.
For example, if I annotated an endpoint with both [BasicAuth] and [BearerAuth] and one returns False on IsAuthorized the whole thing would fail. This makes me think I'm either looking in the wrong place or have an uncommon use-case.
Am I looking in the wrong direction?
AuthorizationAttribute supports different kind of authorizations. It can be used to support Policies or Roles. If you want an OR kind of logic you can use the authorization attribute with a comma separated string for roles. That will let your endpoint accessible by those roles.
Use it like this for OR logic:
[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
}
For AND logic
[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
}
Source is Role-based authorization
I would recommend reading through the whole Authorization documentation.

Authorization in a layered application

I am working on a pretty simple project that is mostly made up of getters and searches and access to certain data is limited depending on the user. I want to use this opportunity to do some best practices when it comes to security, authorization in this case.
The application is activated once at which time a token is generated and used for future requests.
My application has a web api for the endpoint which sits on top of a set of services which sits on top a set of repo's which sits on top of a sql server db. All the controllers do is forward the request down to the service layer.
Here is an example controller:
[ApiAuthorize]
[RoutePrefix("api/Catalogue")]
public class CatalogueController : ApiController
{
private ICatalogueService _catalogueService;
public CatalogueController(ICatalogueService catalogueService)
{
_catalogueService = catalogueService;
}
[HttpGet]
[Route("GetCatalogues")]
public IHttpActionResult GetCatalogues(string branchEan)
{
var catalogues = _catalogueService.GetCatalogues(new GetCataloguesRequest()
{
BranchEan = branchEan
});
return Ok(catalogues);
}
}
My custom authorization attribute checks the token and if valid pulls the user details out from the token and creates a generic principle which is then available in my controllers.
To me the web api is just a way to expose my business\service layer and authorization should be done lower down in my service layer but I can't think of a clean way to get that information down to that layer. In the above example, the service layer will need to check if the user (from the token) has access to that particular branch which means the service layer will need to know who is making the request. The two solutions I can think of is:
1) I am using a request\response pattern for my service layer so I could create an abstract base class called 'Request' as an example which could store all the user details and each request object to the service layer could inherit from this therefore providing user details to my service layer.
public abstract class Request
{
public Request(string username)
{
this.Username = username;
}
public string Username { get; private set; }
}
public class GetCataloguesRequest : Request
{
public GetCataloguesRequest(string username) : base(username)
{
}
}
2) To define an interface, for example ISecurity, which is then injected into my service layer but this would require the layers above my service layer to implement the interface.
I read here - Placing authorization into the service layer rather than Web API layer
- to create an authorization layer but I am not sure of the technical implementation of this.
Any ideas?
What you are looking for is fine-grained, externalized authorization:
fine-grained: you want to create authorization policies that take into account multiple parameters or attributes and possibly relationships between the client (the requestor) and the targeted entity e.g. a listing in your case.
externalized: you want to decouple the business logic from the authorization logic. In your question you complain about how complex the code and the SQL statements are becoming. This is a direct consequence of not clearly separating business logic from authorization logic.
There is a model called attribute-based access control (ABAC) that defines an approach to fine-grained externalized authorization. NIST, the National Institute of Standards and Technology, has produced a report on ABAC which you can read online.
OASIS, the organization for the advancement of structured information standards, has defined a standard called XACML (eXtensible Access Control Markup Language) to implement ABAC.
XACML brings you:
an architecture as illustrated below
The policy enforcement point (PEP) intercepts your API calls. It protects your API, inspects the messages and sends an authorization request to the policy decision point (PDP).
The policy decision point (PDP) evaluates incoming authorization requests from the PEP against a set of authorization policies written in XACML. The PDP eventually reaches a Permit or Deny decision. To reach decisions it may need to look up additional attribute values from databases, web services, LDAP, or files. These are called policy information points in the architecture.
a policy language: the XACML policy language is attribute-based which means it uses attributes to define what can be allowed and what is not. For instance, you could define rules such as:
a real estate agent can see all the listings if and only if the listing location == the agent location
a real estate agent can edit a listing if and only if he/she owns the listing
a real estate agent can close a listing if and only if the listing's item is sold and if and only if the agent is the person that sold the item.
a request/response scheme: XACML also defines a way to query the PDP and to get responses back. A PDP can be queried either via single questions or via multiple questions in a single request e.g.:
Can Alice view listing 123? Yes, permit.
Can Alice view, edit, or delete listing 123? Permit; Deny; Deny.
With a XACML-based approach, you get to maintain your business logic and your API separate from the authorization logic. This has several benefits:
you can always reimplement the API and keep the same authorization model
you can easily expand your API without having to rewrite the authorization
you can change your authorization logic independently of your code
you can audit your authorization logic more easily
your authorization logic is technology-neutral. It works for REST APIs, web services, databases, and more
I recommend you check out the following resources:
the OASIS XACML website
the ALFA plugin for Eclipse - a free tool to write XACML policies.
The XACML developer community
There are both vendor and open-source implementations of XACML:
Axiomatics is a vendor solution that provides both .NET and Java XACML implementations
SunXACML is a long-standing open source Java XACML implementation
HTH,
David.

Retrieving the currently authenticated user in a WCF service

Today, I implemented a custom authentication provider for my WCF service. It is able to determine if my user is valid or not, just as expected.
So, now I have this class:
public class MyCustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
User apiUser = User.Login(userName, password);
// other logic goes here.
}
}
The behaviour of my application depends on what objects the User can access. So, how can I get my User object from here to my service class? There is no immediately obvious way that I can see, as my service class does not inherit from anything by default, unlike the ASP.NET controllers.
My first instinct is to set up a static parameter in MyCustomValidator and then read it from there, but I suspect that a race condition could occur. Can anyone confirm or deny my suspicions?
And most importantly: Is there a better way to do this? This is the first time I have ever used WCF, so I'm not aware of the best practices involved here.
Thank you for your time.
You want to pass some data from validator to service instance. It is bad because you can't do it. UserNamePasswordValidator is only for validating credentials (user name and password). You don't have access to anything from your validator. It even doesn't see current operation context because it runs in different thread. Using static parameter is not a sloution - as you mentioned it is race condition.
I think you need to implement custom authentication and authorization and it is not easy:
WCF Authorizaton, Custom Authorization, Custom credentials and validation

Categories