Help with 2-part question on ASP.NET MVC and Custom Security Design - asp.net-mvc

I'm using ASP.NET MVC and I am trying to separate a lot of my logic. Eventually, this application will be pretty big. It's basically a SaaS app that I need to allow for different kinds of clients to access. I have a two part question; the first deals with my general design and the second deals with how to utilize in ASP.NET MVC
Primarily, there will initially be an ASP.NET MVC "client" front-end and there will be a set of web-services for third parties to interact with (perhaps mobile, etc).
I realize I could have the ASP.NET MVC app interact just through the Web Service but I think that is unnecessary overhead.
So, I am creating an API that will essentially be a DLL that the Web App and the Web Services will utilize. The API consists of the main set of business logic and Data Transfer Objects, etc. (So, this includes methods like CreateCustomer, EditProduct, etc for example)
Also, my permissions requirements are a little complicated. I can't really use a straight Roles system as I need to have some fine-grained permissions (but all permissions are positive rights). So, I don't think I can really use the ASP.NET Roles/Membership system or if I can it seems like I'd be doing more work than rolling my own. I've used Membership before and for this one I think I'd rather roll my own.
Both the Web App and Web Services will need to keep security as a concern. So, my design is kind of like this:
Each method in the API will need to verify the security of the caller
In the Web App, each "page" ("action" in MVC speak) will also check the user's permissions (So, don't present the user with the "Add Customer" button if the user does not have that right but also whenever the API receives AddCustomer(), check the security too)
I think the Web Service really needs the checking in the DLL because it may not always be used in some kind of pre-authenticated context (like using Session/Cookies in a Web App); also having the security checks in the API means I don't really HAVE TO check it in other places if I'm on a mobile (say iPhone) and don't want to do all kinds of checking on the client
However, in the Web App I think there will be some duplication of work since the Web App checks the user's security before presenting the user with options, which is ok, but I was thinking of a way to avoid this duplication by allowing the Web App to tell the API not check the security; while the Web Service would always want security to be verified
Is this a good method? If not, what's better? If so, what's a good way of implementing this. I was thinking of doing this:
In the API, I would have two functions for each action:
// Here, "Credential" objects are just something I made up
public void AddCustomer(string customerName, Credential credential
, bool checkSecurity)
{
if(checkSecurity)
{
if(Has_Rights_To_Add_Customer(credential)) // made up for clarity
{
AddCustomer(customerName);
}
else
// throw an exception or somehow present an error
}
else
AddCustomer(customerName);
}
public void AddCustomer(string customerName)
{
// actual logic to add the customer into the DB or whatever
// Would it be good for this method to verify that the caller is the Web App
// through some method?
}
So, is this a good design or should I do something differently?
My next question is that clearly it doesn't seem like I can really use [Authorize ...] for determining if a user has the permissions to do something. In fact, one action might depend on a variety of permissions and the View might hide or show certain options depending on the permission.
What's the best way to do this? Should I have some kind of PermissionSet object that the user carries around throughout the Web App in Session or whatever and the MVC Action method would check if that user can use that Action and then the View will have some ViewData or whatever where it checks the various permissions to do Hide/Show?

What you propose will not work. Actions can be cached, and when they are, the action (and hence your home-rolled security) does not run. ASP.NET membership, however, still works, since the MVC caching is aware of it.
You need to work with ASP.NET membership instead of trying to reinvent it. You can, among other things:
Implement a custom membership provider or role provider.
Subtype AuthorizeAttribute and reimplement AuthorizeCore.
Use Microsoft Geneva/Windows Identity Foundation for claims-based access.
Also, I completely disagree with ChaosPandion, who suggests making structural changes in your code before profiling. Avoiding exceptions for "performance" reasons is absurd -- especially the idea that the mere potential to throw an exception for invalid users will somehow tank the performance for valid users. The slowest part of your code is likely elsewhere. Use a profiler to find the real performance issues instead of jumping on the latest micro-"optimization" fad.
The correct reason to avoid exceptions for authorizations is that the correct way to indicate an attempt at unauthorized access in a web app is to change the HTTP status code to 401 Unauthorized, not throwing an exception (which would return 500).

Define your authorisation requirements as a domain service so they are available to both the web and web service implementations.
Use an authorisation filter to perform your authorisation checks within the web application, this should be as simple as creating an auth request object and then passing it to your auth domain service.
If the authorisation fails, return the correct error - a 401 as indicated by Craig Stuntz.
ALWAYS authorise the action. If you can hide the link to unauthorised users - thats nice.
Simplify your views / view logic by writing a HtmlHelper extension method that can show / hide things based on a call to the auth domain service.
To use your authorisation service from the web service is simply a matter of constructing the auth request object from something passed in via the service message instead of from a cookie passed by the users browser.

Related

Secure a single action with Forms Authentication & Basic Authentication simultaneously

My MVC application is secured using Forms Authentication. I have a global filter to which applies the AuthorizeAttribute.
I have a controller called Development with an action called Report. I can access this fine by authenticating in the normal way and going to http://localhost:8080/Development/Report. If I am not authenticated then it redirects me to the Forms Authentication login.
I am trying to embed this page into an iOS app so that a user can view the information without having to manually authenticate themselves. To confuse things the iOS app uses a different authentication system, however it holds a device ID and a unique token which my MVC app also store.
What I am trying to do is make the Report action available both via Forms Authentication and from the iOS app using basic authentication where the username will be the device ID and the password will be the token. It's really important that when authenticated using this method the user can only access the Report action. What's the best way to implement this whilst keeping everything secure?
I was thinking of marking the Report action with the AllowAnonymous attribute and then creating a custom authentication just for this action. Is this the best way?
Authentication strategies are just that: strategies. They're not intended to be mixed and matched; you pick one that best suits your application and go with it.
That said, I see two ways forward. Either way, however, will not allow you to use the same action for everything. Your best bet is to factor out shared code into a utility class or similar.
Put the two actions in separate projects. Then each project can implement its own auth strategy. Again, similar code can be factored out into a utility class, and in this case, shared via a class library that both projects may reference.
Create a separate action in the same project and don't use Authorize on it or use AllowAnonymous if it's part of a controller that is authorized. This will essentially turn off the standard auth for this action and provide no protection. However, you're now freed up to do your own "authorization" manually. You can either check the values of device ID and token directly in the action or create an action filter that does so. Which you choose depends on how frequently you need to do this. If this is a one-off you might just want to check directly in the action as that will be quicker and easier. However, if it is one-off you may still want to use an action filter just so you're prepare should its use become more widespread.

ASP.Net Identity using a custom auth provider/service

I am currently developing an ASP.Net MVC web application that requires username and password authentication. I started looking into using ASP.Net Identity for this however I have a very important requirement, the requirement is that the web application itself has no direct access to any databases, all DB Access is to be exposed to the application via an internal REST service. This is due to certain security polices we follow.
I realise that ASP.Net identity is capable of supporting external authentication methods but my question is split into 2 parts.
1) How would I configure ASP.Net Identity to use my custom REST service for authentication?
2) How would I go about developing a service that can be used by Identity for authentication ? (what would need to be returned from the service to ASP.Net Identity)
Any help on this would be most appreciated.
I just did what you are asking about. First, as FPar suggested, you need to implement an IUserStore and pass that to your UserManager. Your custom IUserStore will implement the interface, I used Resharper to generate stubs, but instead of using entity framework, you will use HttpClient to make calls to your REST service.
The REST service will have one action on a controller, I called my identityController, for each of the interface methods you actually need. I implemented the userstore, userloginstore and the rolestore, with code for about 10 calls I actually used. The identitycontroller then is what actually accesses the database.
I also retained the fully async pattern, using async REST calls and Database looks, both with and without entity framework. A shortened version of my data access code is in another question here, regarding IUserLoginStore::AddLoginAsync. In that class I actually used the original entityframework implementation of the user store for part of work, and eventually settled on plain (except for async) ado.net for the parts I couldn't make work that way. The tables are simple enough, using your ORM of choice would not take a lot of time.
Good luck!
You want to implement your own IUserStore and then pass a reference to the UserManager. Look into the Startup and the IdentityConfig files in the standarad ASP.NET MVC with individual user account authentication, to see, how to use them.
You can look here for an IUserStore implementation with entity framework. This is a template, you could start from and change it to your needs. However, you don't have to implement all interfaces, just implement the interfaces, you really need. The UserManager is able to handle that (it throws an exception, if you call a method, that requires an interface, that you don't implement.)
These are two excellent articles on this subject:
http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
http://www.codeproject.com/Articles/762428/ASP-NET-MVC-and-Identity-Understanding-the-Basics

Http handler for classic ASP application for introducing a layer between client and server

I've a huge classic ASP application where in thousands of users manage their company/business data. Currently this is not multi-user so that application users can create users and authorize them to access certain areas in the system.
I'm thinking of writing a handler which will act as middle man between client and server and go through every request and find out who the user is and whether he is authorized to access the data he is trying to.
For the moment ignore about the part how I'm going to check the authorization and all that stuff. Just want to know whether I can implement a ASP.net handler and use it as middle man for the requests coming for a asp website? I just want to read the url and see what is the page user is trying to access and what are the parameters he is passing in the url the posted data. Is this possible? I read that Asp.net handler cannot be used with asp website and I need to use isapi filter or extensions for that and that can be developed only c/c++.
Can anybody through some light on this and guide me whether I'm in the right direction or not?
Note: To be specific, I cannot modify anything in the existing application because there are hundreds of pages (each page again has couple of different actions, such as posted to the same page again) are there in the system and it is really big mess and we are coming up with a different solution to clear that mess but that takes couple of years to complete, meanwhile to provide the multi-user functionality to the users we are trying to do this. This layer acts like layer where we authorize the user to do certain operation or access a page, nothing more than this.
I've worked with an ASP classic website that runs Javascript on the server side. In IIS we selected JScript as the server-side scripting language and access the session variables and the database simultaneously to check user's access rights when they try to check out various parts of the site. What you're describing is completely do-able. Each page needs to have Javascript in <% %> tags and that identifies the content as server-side code. Be careful with security though!
As for the ASP.NET handler, I also developed an ASP.NET application that I added imported to our site (had to use a .NET thread pool) which could handle Ajax requests. IIS has this option to import ASP.NET applications to your site.
You've got options.

Upshot/Knockout Architectural Best Practices - What is the preferred of method of limiting user access to functions exposed through the WebAPI?

A fundamental idea in implementing a single page application with Knockout and Upshot is that most of the data will received from and sent to the server in JSON format using AJAX.
On the server, we will expose a number of endpoints (using perhaps WebAPI and the DbDataController) to respond to requests from Upshot. These endpoints may provide general queries for data such as lists of clients, previous orders, account information, etc.
Obviously, it is not desirable for one client to be able view another clients account information, previous orders, or other private data.
What strategies or approaches be used to secure queries (and data) which are being requested from upshot (or other mechanism) to the server? (In other words, how do we make sure a user only has access to his own data?)
Are the strategies the same or different than those used in a normal ASP.NET MVC application--namely use of the Authorize attribute?
This is probably a very simple question, but I am still not clear on all the differences between WebAPI controllers and normally ASP.NET MVC controllers.
Thank for your help!
A custom authorize attribute is one possible way to implement this requirement. The only difference with standard ASP.NET MVC controllers is that you derive from System.Web.Http.AuthorizeAttribute instead of System.Web.Mvc.AuthorizeAttribute.

Securing a mvc view so only the server can access it

I'm building a .Net MVC app, where I'm using one particular view to generate an internal report. I don't want the users of the site to gain access to this page at all.
I've a console app that fires every so often which will scrape some of the details from this page by hitting it's URL.
I don't like the idea of having the URL hanging out there but I'm not sure of another way to go about it.
Thoughts on what might be the best practice way for tackling this?
Edit:
Here's what I ended up doing, created a new WCF Service project in the solution. I also copied basically what was the MVC view page into a new standard web forms page in this project. On top of adding security via the regular .net Authentication methods (eg set only valid windows users can access the page), I can also lock down the vhost to only be accessed by certain IP's.
The best practice would be to expose a wcf service for this, and set up a security model that is different than website.
If you must use MVC the best approach use forms authentication with mvc and set
[Authorize(Roles = "SecureUser")]
On the View.
If the view never needs to be rendered at all except to provide data for the console app, then why not have the console app simply connect to your database to get the data directly instead of going through the web app? You could still do this for the console app even if the view does need to be available for some users, then control access to the view using the Authorization attribute, which could suitably restricted now that an external app need not have access to it.

Resources