I'm building an application in ASP.NET MVC4 as a learning exercise. I'm trying to understand
authentication and authorization. That seems fine, role based authorization seems fine for restricting certain controllers/actions to users who are part of a given role.
What I'm struggling with is how I can apply this to data which belongs to an individual user. Using a forum as a simple example how could the functionality be achieved whereby a user can only edit or remove posts that they have created but can view/add comments to posts of other users. Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.
Is there a more elegant solution that can be applied rather than applying this kind of logic to multiple controllers/actions?
There's a wealth of information out there I'm just trying to narrow the search. Can anyone suggest a good tutorial/article on this. I've been looking at Forms authentication and Membership but I'd be interested in something using Identity too. I'm also using Entity Framework.
Thanks
Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.
Yes, that's exactly what you do. While role-based authorization is a matter of a simple relation between users and roles, data-access level authorization is usually complex and involve custom business rules.
Of course, it could help a lot to create a thin layer of managers that will be commonly used as guards so that you keep all the code close together:
[HttpPost]
public ActionResult PostFoo( FooModel model )
{
// keep the access manager separate from the
// domain layer. operate on IDs.
if ( new UserAccessManager( this.User ).
CanOperateOnFoo( model.IdSomething, model.IdWhateverElse ) )
{
}
else
// return 403 or a meaningful message
}
or
[HttpPost]
public ActionResult PostFoo( FooModel model )
{
// switch to the domain layer
Foo foo = Mapper.Map( model );
// make the access manager part of the domain layer
if ( foo.CanBeOperatedBy( this.User ) )
{
}
else
// return 403 or a meaningful message
}
Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.
No, you want to avoid hard-coding authorization logic into your code. Doing so leads to:
authorization silos
poor visibility
a chance there might be errors in the authorization logic
hard-to-maintain logic
Is there a more elegant solution that can be applied rather than applying this kind of logic to multiple controllers/actions?
Yes, there is. Much like you wouldn't hard-code authentication or logging into your app, you want to externalize authorization. This is called Externalized Authorization Management (EAM). There are several frameworks that help you do that from Spring Security in Java to Claims-based authorization in .NET to XACML-based solutions.
There are 2 fundamental authorization models you want to consider:
role-based access control (RBAC)
attribute-based access control (ABAC)
You can read about both on NIST's website (RBAC | ABAC).
Given the sample rule you gave:
A user can only edit or remove posts that they have created but can view/add comments to posts of other users.
RBAC will not be enough. You will need to use ABAC (and XACML) to be able to implement the relationship between the user and the data requested. XACML, the eXtensible Access Control Markup Language is a standard that provides you with:
a standard architecture.
a request/response scheme, and
a policy language.
With the XACML policy language, you can rewrite your example as:
A user can do the action==edit or the action==remove if and only if the post.owner==user.id
A user can do the action==view on any post
A user can do the action==comment on any post
Then, from your code, all you have to do is send an authorization request: Can Alice view post #123?. The authorization engine (also called policy decision point or PDP) will determine who owns the post and will reach a decision, either of a Deny or a Permit.
A key benefit to using externalized authorization and XACML is that you can apply the same consistent authorization to any layer (presentation tier, business tier, ESB, APIs, databases...) and any technology (Java, .NET, Python...).
Other benefits include:
modular architecture
configuration-driven authorization that is easy to grow as requirements change
easy-to-audit authorization
centrally-managed authorization
cheaper to develop and onboard new applications than writing code over and over again
standards-based.
There are several open-source and vendor solutions out there that address this market. Have a look at Axiomatics (disclaimer: I work for Axiomatics) or SunXACML (open source).
HTH,
David.
Related
I'm converting a Symfony1 application to Symfony2, and I'm trying to follow Symfony2's best practices.
I have a problem with the business logic: In the old app, all the logic was in the controller (very fat controllers). I've moved it to entity repositories, but I'm not sure if this is the correct way (because, aside other things, I need to send emails, and this isn't working).
For example, the save function for a resource reservation manager (calendar) is:
Begin transaction
Validate that the given resource isn't used in the time-lapse I'm trying to save
If the data is correct and the resource is marked as "mandatory confirmation", an email is sent to all the users from the "confirmers" group
An email is sent to the current user telling him that the resource has been reserved correctly (and, if needed, telling that a "confirmer" must approve his reservation)
If all has worked well, commit the transaction. If any error has happened, rollback the transaction
As you can see, there is lots of business logic (this example is one of the easier modules), using multiple kind of entities, users, emailers, etc. So, how can I organize it? Should I put the business logic in an entity repository, or is better to use services? And for the emails, maybe it's better to send them from an event listener? And do you know where can I find some examples about this?
Simply make services to handle these tasks. For example; create a service that you can re-use, that's testable, for sending emails. Make the API as simple as it can be, and then you can use it in your controller.
The way I think about it is that the controller is ONLY there to send information around various services, and to handle what is output to the user. Anything else should be controlled via services, and the responses from those services.
It's not a bad thing to have small classes - your classes should aim to do one thing, and one thing well. If you split them up enough then they'll be easily testable, and easily reusable.
The Symfony Books are excellent resources for this kind of thing:
http://symfony.com/doc/current/book/service_container.html
You might find this article of Martin Fowler's useful. He says…
In general, the more behavior you find in the services, the more likely
you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you've robbed yourself blind.
I suspect he and Eric Evans would implement your business logic using a DDD approach along the lines of…
class Resource
{
public function isUsedIn(TimePeriod $tp);
public function isMandatoryConfirmation();
}
class ReservationManager
{
public function save(Resource $r, TimePeriod $tp)
{
if (! $r->isUsedIn($tp) || $r->isMandatoryConfirmation()) {
// send email to all the users from the "confirmers" group
// send email to the current user
}
}
}
Unfortunately in my experience with Symfony2, this hasn't been done and the code has ended up inside services. Symfony acknowledge that business logic can be put into Doctrine entities but from my point of view, it is a bit of weasel offer.
Services are container aware and as such can easily access other services to perform other functions like sending emails, logging messages. Doctrine entries cannot access other services which means that like Seer, in our project, we end up using services.
If you like the idea of moving more of your business out from services, it isn't difficult however Doctrine & Symfony do not seem to support it out of the box :-(
I am currently building an ASP.NET Web API which unique purpose is to provide data to a Windows Phone app. I already finished the Web API development and I published it in an Azure website for testing purpose.
It works like a charm but my issue now is that this Web API is now publicly accessible. What I would like is to find the simplest way to limit the audience to my particular Windows Phone app and nobody else. I first thought of using an API key but it does not seem that ASP.NET proposes this as a builtin option. The builtin options are not satisfying either because their require a login.
Basically I want that only my Windows Phone app can access the Web API and that this authorization is transparent for the user (no authentication required). Any suggestions?
PS: The Web API is deployed on Azure, will not be distributed to other developers and securing with HTTPS is a possibility.
I did an implementation and blogged about it : http://www.ucodia.fr/blog/simple-authorization-asp-net-web-api/
As you're looking for a very basic, stop the casual hacker method, there is a simple technique that can be used with the Web API and ActionFilterAttributes. As there are two identically named attribute classes with that name, make sure you're using the one from System.Web.Http.Filters.
It would be very common to send a token of some sort, that would either be generated, or encoded permanently into the application. So, in this example, a header value would be encoded into every request, and then checked using the filter.
[VerifyToken]
public class MyAPI : ApiController
{
}
public class VerifyTokenAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext filterContext)
{
// get the token from wherever you'd like ...
var token = filterContext.Request.Headers.GetValues("Token").First();
if (token != GetCurrentToken())
{
filterContext.Response =
new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
base.OnActionExecuting(filterContext);
}
}
Does it need to be truly secure? or just secure enough?
For 'secure enough', I will usually just use an API key as you suggest that the client app passes to the back-end and for which the back-end will not respond if the key doesn't match. This will provide a very basic level of security to prevent someone who just happens along from executing arbitrary api calls; for read only, non-confidential data this has usually been enough for me.
For a bit of added level of security you could you a rotating time-sensitive api key that changes based on the time of the day (with perhaps a sliding window to account for minor clock differences between clients and server). This ups the security by obscurity just a bit more, requiring someone to do a bit more work before they crack your code.
Depending on your app, it might also be a good idea to consider rate throttling your API responses as well, if there is a discernible max number of calls any given client should make to your API, you could geometrically slow down the responses to thwart attempts at misuse if someone does bypass your security.
I am having troubles wrapping my head around the concept of multi tenancy in combination with websecurity (webmatrix framework from microsoft). I am building a mutli tenant website with:
mvc4
entityframework6
websecurity (from webmatrix)
Authenticate
I can allow users to register & login using the WebSecurity methods. I can verify if a user is logged in / is authenticated via User.Identy.IsAuthenticated.
Determine Tenant
I determine the tenant via the url ([companyname].domain.com).
Register a new customer
A new customer can create a tenant via the registering form in my application. If a user registers (without having a companyname present in the url) he will have to give some account inputs as some company inputs. He will then create a new alias which is conform companyname.domain.com. So, long story short, a Tenant is always coupled to 1 or more user(s) (1-N).
Requirement
I need to guarantee that a user from Tenant 'abc' will never be able to login to Tenant 'xyz'. (Therefore I also don't like the WebSecurity framework too much, as it seems a shared database for all my tenants (or am I wrong?)).
My question
Could you guys share some insights in how to handle the check on "tenant" and "authenticated user" in real world multi tenant applications?
The hot topics for me:
Do you validate the tenant + authenticated user once, or in every action in every controller?
Is it safe to rely on the default websecurity class or would I be better of designing my own user tables or are customer MembershipProviders the better alternative?
Should I use cookies or is that a very bad choice.
I would be very much helped if you could share some documentation where I can read all about these questions. I have the strong desire to see some more in detail documentation about multi tenancy, that dives into the actual design (maybe even code examples).
I already read through most of the "general documentation" / "commericial presentations":
http://msdn.microsoft.com/en-us/library/aa479086.aspx
http://www.businesscloud9.com/content/identifying-tenant-multi-tenant-azure-applications-part-2/10245
http://msdn.microsoft.com/en-us/library/windowsazure/hh689716.aspx
http://www.developer.com/design/article.php/3801931/Introduction-to-Multi-Tenant-Architecture.htm
If needed I'll rephrase / add code / do whatever is needed to get help.
Many thanks in advance.
Each solution you could get here would be dependent on what your app does and how it works with data, if you use repository pattern, if you use IoC etc. You might consider instantinating your repository by passing userid to repository class and doing filtering everytime application needs data, you can do that in your controller - this approach is used very often (even in VS SampleProjects - like "SinglePage Application" you might want to download some open source projects and just see how it's done there.
What I do in some of my projects where nothing "really fancy" is required and I don't expect a huge load is this:
- I setup BaseController that every other controller needs to implement
- in onActionExecuting event of the BaseController I do
public Employee CurrentEmployee { get; set; }
protected override void OnActionExecuting(ActionExecutingContext ctx)
{
base.OnActionExecuting(ctx);
string authenticatedUser = User.Identity.Name;
CurrentEmployee = mortenDb.Employees.FirstOrDefault(e => e.Account.Login == authenticatedUser );
}
so in all other controllers I'm able to refer to an Employee object that belongs to currently logged in user. You could do the same with your Company object. So I assume you would query Employees like I do and retrieve the Company reference and pass it to public property on your BaseController. It's maybe not the best solution, but it's rather secure as long as you remember to pull out data via Company object navigation properties (eg. Employees, Tickets, Requests etc. whatever you have in your Model )
All the security stuff I have worked with in the past in ASP.Net for the most part has been role based. This is easy enough to implement and ASP.Net is geared for this type of security model. However, I am looking for something a little more fine grained than simple role based security.
Essentially I want to be able to write code like this:
if(SecurityService.CanPerformOperation("SomeUpdateOperation")){
// perform some update logic here
}
I would also need row level security access like this:
if(SecurityService.CanPerformOperation("SomeViewOperation", SomeEntityIdentifier)){
// Allow user to see specific data
}
Again, fine grained access control. Is there anything like this already built? Some framework that I can drop into ASP.Net and start using, or am I going to have to build this myself?
Have you looked at Authorization Manager (AzMan)? http://msdn.microsoft.com/en-us/library/bb897401.aspx
It was included with Server 2003 and has had a few updates in server 2008, and comes with an MMC admin tool.
You can store you data in an xml file or AD/ADAM partition using server the 2003 version, and in server 2008 they added SQL support.
This tool lets you link your security objects together in a hierarchical structure of roles, tasks & operations.
You can use this as a role based provider in Asp.net but they also include .net classes so you can access the authorization store contents directly.
I think you might be looking for Declarative security. Declarative security allows you to well, 'Declare' who can access what as attributes on the code here is a page on Role Based security also on MSDN. Here is an example:
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="admins")]
public class foo
{
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="Domain Admins")]
public void bar()
{
....
}
}
I am trying to build an ASP.NET 3.5 website that allows users to log in and browse a couple of pages. I would like to restrict certain users to be able to view certain pages but I'm having trouble coming up with a custom and flexible system. I have seen MS's version of this but it's not what I am looking for. Can anyone direct me to some good online articles or even a video tutorial so I can do further research. Thanks!
P.S. I have tried creating a class that inherits from System.Web.UI.Page which does some checking but it's getting messy. All my other pages inherit from that common page. Is this a common practice? How have you guys solved this problem in the past?
The best way to implement this would be, Forms Authentication coupled with Custom Role Provider.
Hope you know, for Forms Authentication to work, you need not have to use the Complete Database Setup that MS uses to Authenticate.
You can simply have your own Database and Validate a user yourself, and just set the cookie.
String UserName = "CoolGuy";
Boolean isValidUser = YourClass.YourMethod(UserName);
if (isValidUser)
{ FormsAuthentication.setAuthCookie(UserName, false); }
This will authenticate the user "CoolGuy" for the session, provided YourMethod returns true.
You can use this, coupled with custom role provider. This gives you the facility to check User.IsInRole("Role"); in your code.
To Start with CustomRoleProvider.. here is a good reference... http://davidhayden.com/blog/dave/archive/2007/10/17/CreateCustomRoleProviderASPNETRolePermissionsSecurity.aspx
Raja
Well, without knowing the exact details of your app, one thing you could use is the Role Manager built into the Membership API.
Basically, you would create roles for each page and assign users to the roles (pages) you would want them to view.
In the code behind for each page, on the On_Load event, I would simply call the method
if(Roles.IsUserInRole(rolePageName))
{
//Continue page loading logic
}
{
//Redirect or transfer the user elsewhere
}
For this kind of logic you may want to reconsider using an inherited page, otherwise you're going to have to come up with a way to retrieve the URL of the page and pass that into some long list of if-else or switch statements to call the proper Roles.IsUserInRole method.