ASP.NET MVC: seperatation of concern for normal/admin user - c#

I'm going to separate admin and normal user section of my ASP.NET MVC 5.2 project. My admin area and normal user area have much things shared, however privileges and details for each of them is different.
Right now I don't know how to separate admin area and normal user area. I don't know if I should create different project for admin-panel or I just should route admin to different path and use the same controllers? Or should I route to different path and use different views/controllers?
And a side question, is it possible to have real physically separated admin and normal user area in the same ASP.Net MVC solution or not?

Usually in applications there are various endpoints using the same business logic. What should we do in this scenario? We can easily copy one endpoint and paste it in another, but once the business case is changed, we'd need to change everywhere in our code.
In favor of separation of concerns, controllers should have "code" logic and another layer should have the "business" logic. E.g. Controllers might define how properties are named, but not how long an username is. An username should be long at least 3 chars no matter which controllers tries to register the user.
All of that operation with entity models to meet the business case requirements should be moved to a separate layer. Usually called Service layer.
That all of your controllers can use any of that services without being aware from the business scenario behind.
A simple example here are two controller actions - one of the - editing your own profile and the other - the administrator editing an arbitrary user profile.
[Authorize]
public IActionResult Edit(UserViewModel model) {
if(model.Id != this.CurrentlyLoggedUser.Id) {
return this.RedirectToAction(...);
}
var userService = new UserService(); // inject maybe
userService.EditById(model.Id, model);
return this.View();
}
and the admin action
[Authorize("Admin")]
public IActionResult Edit(UserViewModel model) {
var userService = new UserService(); // inject maybe
userService.EditById(model.Id, model);
return this.View();
}
The "code" logic here is - create service, invoke the encapsulated edit logic. Also some security reasons the action should take care about - Authorize and Authorize Admin.

Related

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.

C# .NET 4.5 activity-based authorization WebForms (not MVC)

Currently I’m trying to implement activity-based authorization in my webform application. In my application you have different roles: Admin, manager, employee, and trainee.
The application communicates with my database through my BLL (business logic layer) and what I’m trying to do, is have authorization on method level in the BLL for all the reader and manager files for all my entities, like so:
[Authorize(Activity = "CreateUser")]
public static void InsertUser( ... )
[Authorize(Activity = "UpdateEmployee")]
public static void UpdateEmployee( ... )
For every method I want a CRUD activity and in the database I want to tell which roles gets to do what activity, or something that´s a lookalike like this.
Role-based security is not an option, besides for logging in, because a trainee for example is not allowed to insert or delete any data, except for one entity. So I need a permission/activity based authorization in my webforms.
Currently all I can find are solutions for MVC and .NET Core, but not any for the webforms, or the posts are from 2011 ish which don't really offer a solution, and I wonder if anyone has any new ideas or solutions as of this time.
In my project I make use of FormsAuthentication, and in my webconfig file I autorize specific roles and paths for specific roles. But this won’t cut it. I also make use of the Application_OnPostAuthenticateRequest in the global file with the FormsIdentity with my custom principal class which makes use of the IIDentity and IPrincipal.
Also, my AddEdit pages are the same page, and based on the querystring passed in the URL, like a userId, or employeeId, the save button decides whether it's an insert or update. So this is the reason why I need auth on methods.
So my question, does anyone know a pattern that I can actually implement in asp.net 4.5 webforms that gets permission or activity based authorization without having to hardcode everything so it's more future proof?

Understanding srp principle in solid with nlayers

I have a web application with the following layers:
View
Business
Entities
Repository
I want to send an email to a User when he or she is registered.
I have the class User, in the Entities layer, and the classes UserBussines and MailBusiness in the Business layer.
The problem is that I don't know where is correct to send the email to the user.
I see some options
1) In the controller:
UserBusiness.AddUser();
MailBusiness.SendEmail();
2) In the business
UserBusiness.AddUserAndSendEmail()
{
AddUser();
MailBusiness.SendEmail();
}
In the two options I think that I'm not fulfilling the SRP in the SOLID principle, because I'm giving two responsibilities in one method.
I'm not understanding the principle? Or am I doing something wrong?
You have user registration scenario:
Given not registered user
When user registers
Then user becomes registered
And greeting mail is sent
This scenario should exist in your business logic layer, because:
It is scenario of your business domain
It should exist whether you use web application, desktop application, or mobile application.
So, you should have some application service (e.g. UserService) which will act as coordinator for user repository and email service:
public void RegisterUser(User user)
{
// possibly you should also check that user is not registered yet
_userRepository.Add(user);
_emailService.SendGreeting(user);
}

Why is it bad practice to secure MVC routes?

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.

Simple Membership Admin Accout

I am working on my first ASP.Net MVC 4 application and now stuck with one simple use case.
I need to authenticate one single user (Admin) so that he/she can log in to admin area to perform certain tasks. Though the ASP.Net internet project template has Account controller using simple membership but that seems to have much more than what I actually need. For instance, I don't really need the user registration functionality and user roles. My requirements are fairly simple, just to store one single user in database, give him the options to update his info like password, email etc and grant him access to admin area (admin controller and actions).
What I can't figure out is
Are simple membership or other asp.net membership provider my only options for this simple scenario.
If not what other option do I have in order to use [Authorize] to secure admin actions
You can build a custom method to grab the user and their stored role, then evaluate it in your controller. So, for instance:
public ActionResult GetAdminPage()
{
var loggedInUserName = HttpContext.User.Identity.Name;
var user = somesortofproviderlookupmethod(loggedInUserName);
// Assume user is a bool and is true
if (user)
{
return view("AdminPage");
}
}
The only thing I'm not sure of is whether or not HttpContext.User requires membership. Perhaps someone can shed some light. If so, perhaps you could send the username from the view, but then of course you're trusting the client. So how you are doing user authentication would change this answer somewhat.
Personally, I like membership. It's clean, easy, fast and can be scaled nicely if you end up having additional requirements. Doing something like this would be even easier with membership, since then you can actually use Roles.GetRolesForUser(); and only return the admin view if they contain the role you are looking for.

Categories