So I have been coming across stuff over the last few weeks which is making me improve my understanding of REST.
At work we are having issues with some rest api resource access which has some pretty complex access, so I was wondering if someone could help me understand if/what we are doing wrong and what is the right way go about it.
So the issue we're having is that we have an endpoint for getting all orders. e.g. /orders this endpoint has pagination and filters etc, this endpoint will get a list of orders.
We have two main types of users (admin and account).
If you are an admin, you are able to see all the orders, if you are an account user, it gets a bit more tricky because account users can see orders based on a set of permissions.
So by default, an account user can see all orders that they have placed. They will also be able to see any orders that they have for them. (so this distinction here is that orders are placed by a user, but can be for another. e.g. I might order something for another user).
Due to the way the application is designed, users are able to see orders for other branches as well, one example would be a branch reporter that deals with the orders from all branches and collates reports etc.
So an example for all of this would be:
if you are an administrator, you see all orders by default, if you are an account user, and have permissions for branch x and y, you will see all orders for x & y as well as any orders placed by yourself.
Is the domain design faulty here, is that what's stopping me from seeing a feasible solution?
I have been looking about user contexts a bit so that might be a way to split some of the issues a bit. So an example is different users see different resources in different ways. So to not make a one size fits all solution (which this definitely is) you should build 3 apis. If I did that I could definitely separate admin from account. But I dont know what to do with the complexity of accounts.
I have a suspicion that the key to this relates to removing these permissions checked out of the database and move them into permission, but I am not sure how one would handle dynamic permissions.
I am sorry if a lot of this is rant or is this doesn't make sense. Any help would be appreciated even if it's only to put me on the right path.
Like I said, I have been trying to understand how to configure REST while trying to forget about the underlying database, but a problem as bonkers as this stumps me.
I think you are mixing 2 important aspects, the first is the style you want your API to follow, the second is the authorisation logic you want to apply.
REST
If you want to build a consistent, clear, and maintainable rest API first you need to understand your domain.
So what is an Order for you, who is going to consume your API, is your code base unique and so has it to be, or can be split reducing complexity, coupling and increasing the isolation?
If you have a single understanding of Order, just leave it as it is.
Authorisation
The authorisation rules are just another example of business logic, and this are often subject to change as the business evolves.
I suggest you to treat the authorisation as you treat any other logic, like when you calculate an order total.
So if you have a service layer, create an Authorisation service where you check what a user is allowed to see.
You can also do it in a filter, so that before returning the list of orders, you apply the security rules and you remove all orders that the user is not supposed to view.
You don't like this approach? Then you need to move the "authorisation filters" down the stack so that the query itself takes it into account.
Based on what you said there are various aspects which you need to account when performing a GetOrderByUserID(x), if you use EF, you can generate the authorisation filters as lambda expression and you can add it to your where clause, making sure you and the necessary joins so that you can take the branch, accounts and so on.
Conclusion
It is down to you how you want your system to implement the security, but unless you recognise the existence of multiple domain objects Order, BranchOrder, DelegatedOrder, AccountOrder and so on, in the request there should be no evidence of the security that will be applied afterwards, the only thing is that the authorisation of the REST request has to carry enough details, likely in the headers, to identify who is requesting the resources.
Also note that even if you break down your domain object (Order) into more specific types of order, you will still need to apply security, and therefore you will still need to create and maintain the security rules.
Your question is a bit broad and with just enough information to give you hints, if you want a more specific answer, you need to update your question to be more specific as well.
If you have code level access at "orders" end. Then you can design in this way.
Make the user's id as a mandatory input at the "Orders" end. So whenever any user calls the API, he should make the request with parameters of User ID.
Once you get the user ID at "orders" end, check the authorization of user such as whether user is admin or not and user has access to which branch.
Now, Limit the data in response accordingly.
You should make the changes at "Orders" end to authorize, filter the data and sending the response accordingly.
Related
In a windows forms payroll application employing MVP pattern (for a small scale client) I'm planing user permission handling as follows.(Roll based)
NOTE : System could be simultaneously used by few users (maximum 3) and the database is at the server side.
User Tables in the database.
USER (user_id[pk], name, access_level, status)
PERMISSION (permission_id[pk], permission_detail)
USER_PERMISSION (user_id[pk][fk], permission_id[pk][fk])
I would maintain user list in USER table and permission list in PERMISSION table (permission details are the accessible module names). Intermediate table USER_PERMISSION would map the users with the permissions. UESR and PERMISSION tables have 1:M relationships with USER_PERMISSION table.
When an user login to the system, first the system will validate the user and if its valid then the home screen will be shown and the logged user's ID will be hold in a global variable (accessible to all presenter classes) . When the user try to access a specific module, the system will read that global variable to find the current user's ID and then it will look in the USER_PERMISSION table whether there is an entry relevant to that user id and the module name in which the user is trying to login. If there is and entry, then the user will be given the access to that particular module.
When user log off the variable holding the current user id will be cleared.
In this approach is it okay to hold the current user's ID in application memory? or should be written to a local file?
Modifications to the data in the tables should be tracked and in this purpose should I maintain a separate column on each table (ones should be monitored) to hold the ID of the user who is modifying the record?
EDIT:
Can we use SQL-SERVER user rolls/ logins in this purpose? and can this user action login stuff be handed over to SQL-SERVER?
When controlling Read/Write permissions in Forms, the respective Presenter handle the logic and set the properties in the View (properties like IsModifyAllowed{get;set;}, IsDeleteAllowed{get;set;} etc.) according to the current users permissions. So that the View could handle the rest of the things by enabling / disabling controllers in the View.
In this approach should the every Model have a matching property like in the view(in this case IsModifyAllowed{get; set;} etc. )?
What is the most widely used approach in this case?
What you have described in your first part of the question is pretty common, although it's not actually Role based, it's permission based.
It's not a perfect solution, although no security mechanism really is. But it's pretty simple and works.
To answer your questions.
There shouldn't be a problem with holding the id in memory, so long as we're not talking about government level security here, and there is no real concern about people breaking into the machines and trying to gain access, in which case there are probably much bigger fish to fry. Storing it in a file may actually make it less secure, and you would eventually have to read it into memory at some point anyways.
Tracking changes can be simple or complex, depending on how you want to do it. You can add a last modified field, but this will only track the most recent change. To be safe, you need an audit table that tracks all changes and keeps historical versions of the data. It's probably a good idea to do this audit table with a trigger so that your application code doesn't have to remember to do it.
Yes, you can use SQL server logins and roles, but this probably won't make things easier or less complex. With your model, you're controlling access to modules via a permissions table. Using SQL Server Roles, you would have to control access via data, and react to exceptions thrown for not being able to access things, or query the database for roles and have to do things in tables anyways. If you have Windows domain, you might want to consider using Active Directory instead.
I don't completely follow what you're saying about Views and Model properties, because you haven't adequately explained your models.
There is no "most widely used approach", everyone does it differently. Although there are a number of things people tend to do. Microsoft offers a number of approaches, for instance they have what's known as the Composite UI Application Block and Authorization Manager. You can read about an interesting impelementation here: Granular Role Based Security. Jesse Liberty offers another take Here
In short, this is something you will have to work out yourself, because there are literally thousands of ways people have done this (if not millions). Do some research, and try to come up with what works best in your situation.
Ok guys, another my question is seems to be very widely asked and generic. For instance, I have some accounts table in my db, let say it would be accounts table. On client (desktop winforms app) I have appropriate functionality to add new account. Let say in UI it's a couple of textboxes and one button.
Another one requirement is account uniqueness. So I can't add two same accounts. My question is should I check this account existence on client (making some query and looking at result) or make a stored procedure for adding new account and check account existence there. As it for me, it's better to make just a stored proc, there I can make any needed checks and after all checks add new account. But there is pros and cons of that way. For example, it will be very difficult to manage languagw of messages that stored proc should produce.
POST EDIT
I already have any database constraints, etc. The issue is how to process situation there user is being add an existence account.
POST EDIT 2
The account uniqueness is exposed as just a simple tiny example of business logic. My question is more abour handling complicated business logic on that accounts domain.
So, how can I manage this misunderstanding?
I belive that my question is basic and has proven solution. My tools are C#, .NET Framework 2.0. Thanks in advance, guys!
If the application is to be multi-user ( i.e. not just a single desktop app with a single user, but a centralised DB with the app acting as clients maybe on many workstations), then it is not safe to rely on the client (app) to check for such as uniqueness, existance, free numbers etc as there is a distinct possibility of change happening between calls (unless read locking is used, but this often become more of an issue than a help!).
There is the ability of course to precheck and then recheck (pre at app level, re at DB), but of course this would give extra DB traffic, so depends on whether it is a problem for you.
When I write SPROCs that will return to an app, I always use the same framework - I include parameters for a return code and message and always populate them. Then I can use standard routines to call them and even add in the parameters automatically. I can then either display the message directly on failure, or use the return code to localize it as required (or automate a response). I know some DBs (like SQL Svr) will return Return_Code parameters, but I impliment my own so I can leave inbuilt ones for serious system based errors and unexpected failures. Also allows me to have my own numbering systems for return codes (i.e. grouping them to match Enums in the code and/or grouping by severity)
On web apps I have also used a different concept at times. For example, sometimes a request is made for a new account but multiple pages are required (profile for example). Here I often use a header table that generates a hidden user ID against the requested unique username, a timestamp and someway of recognising them (IP Address etc). If after x hours it is not used, the header table deletes the row freeing up the number (depending on DB the number may never become useable again - this doesn;t really matter as it is just used to keep the user data unique until application is submitted) and the username. If completed correctly, then the records are simply copied across to the proper active tables.
//Edit - To Add:
Good point. But account uniqueness is just a very tiny simple sample.
What about more complex requirements for accounts in business logic?
For example, if I implement in just in client code (in winforms app) I
will go ok, but if I want another (say console version of my app or a
website) kind of my app work with this accounts I should do all this
logic again in new app! So, I'm looking some method to hold data right
from two sides (server db site and client side). – kseen yesterday
If the requirement is ever for mutiuse, then it is best to separate it. Putting it into a separate Class Library Project allows the DLL to be used by your WinForm, Console program, Service, etc. Although I would still prefer rock-face validation (DB level) as it is closest point in time to any action and least likely to be gazzumped.
The usual way is to separate into three projects. A display layer [DL] (your winform project/console/Service/etc) and Business Application Layer [BAL] (which holds all the business rules and calls to the DAL - it knows nothing about the diplay medium nor about the database thechnology) and finally the Data Access Layer [DAL] (this has all the database calls - this can be very basic with a method for insert/update/select/delete at SQL and SPROC level and maybe some classes for passing data back and forth). The DL references only the BAL which references the DAL. The DAL can be swapped for each technology (say change from SQL Server to MySQL) without affecting the rest of the application and business rules can be changed and set in the BAL with no affect to the DAL (DL may be affected if new methods are added or display requirement change due to data change etc). This framework can then be used again and again across all your apps and is easy to make quite drastic changes to (like DB topology).
This type of logic is usually kept in code for easier maintenance (which includes testing). However, if this is just a personal throwaway application, do what is most simple for you. If it's something that is going to grow, it's better to put things practices in place now, to ease maintenance/change later.
I'd have a AccountsRepository class (for example) with a AddAcount method that did the insert/called the stored procedure. Using database constraints (as HaLaBi mentioned), it would fail on trying to insert a duplicate. You would then determine how to handle this issue (passing a message back to the ui that it couldn't add) in the code. This would allow you to put tests around all of this. The only change you made in the db is to add the constraint.
Just my 2 cents on a Thrusday morning (before my cup of green tea). :)
i think the answer - like many - is 'it depends'
for sure it is a good thing to push logic as deeply as possible towards the database. This prevent bad data no matter how the user tries to get it in there.
this, in simple terms, results in applications that TRY - FAIL - RECOVER when attempting an invalid transaction. you need to check each call(stored proc, or triggered insert etc) and IF something bad happens, recover from that condition. Usually something like tell the user an issue occurred, reset the form or something, and let them try again.
i think at a minimum, this needs to happen.
but, in addition, to make a really nice experience for the user, the app should also preemptively check on certain data conditions ahead of time, and simply prevent the user from making bad inserts in the first place.
this is of course harder, and sometimes means double coding of business rules (one in the app, and one in the DB constraints) but it can make for a dramatically better user experience.
The solution is more of being methodical than technical:
Implement - "Defensive Programming" & "Design by Contract"
If the chances of a business-rule being changed over time is very less, then apply the constraint at database-level
Create a "validation or rules & aggregation layer (or class)" that will manage such conditions/constraints for entity and/or specific property
A much smarter way to do this would be to make a user-control for the entity and/or specific property (in your case the "Account-Code"), which would internally use the "validation or rules & aggregation layer (or class)"
This will allow you to ensure a "systematic-way-of-development" or a more "scalable & maintainable" application-architecture
If your application is a website then along with placing the validation on the client-side it is always better to have validation even in the business-layer or C# code as well
When ever a validation would fail you could implement & use a "custom-error-message" library, to ensure message-content is standard across the application
If the errors are raised from database itself (i.e., from stored-procedures), you could use the same "custom-error-message" class for converting the SQL Exception to the fixed or standardized message format
I know that this is all a bit too much, but is will always good for future.
Hope this helps.
As you should not depend on a specific Storage Provider (DB [mysql, mssql, ...], flat file, xml, binary, cloud, ...) in a professional project all constraint should be checked in the business logic (model).
The model shouldn't have to know anything about the storage provider.
Uncle Bob said something about architecture and databases: http://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html
I am trying to achieve the following:
Authenticate users against Active directory.
If the user belongs to group "A" i want to limit user rights
If the user belongs to group "B" i want to have some other logic in my code.
I am able to achieve the first one in the above list.
I am using forms authentication in my web application(Intranet).I did some research and there are various suggestions to use Microsoft Active Directory Application Mode (ADAM) which i m completely unaware of.Is there a way i can achieve the above with out using ADAM? Say suppose get the group list into the code and based on that can i make a call if user belongs to some group and so on..
Is is that i am thinking only on group level which limits my options?
Or is there a way other than giving user access rights from group level
or am i completely not understanding the concept of Active directory authentication ?
Check this question, it is the same problem though differently described: Validate a username and password against Active Directory?
Either way ActiveDirectory is fully supported within C#, no need for additional systems (I am not aware what ADAM is either).
To check the groups of a username, use this code:
UserPrincipal p = UserPrincipal.FindByIdentity(
domainContext, IdentityType.SamAccountName, userName);
var groups = p.GetGroups();
foreach (GroupPrincipal g in groups) { /* do something */ }
If you are asking about a general architectural or best practices question, I would suggest looking at Claims Based Authentication. In particular Active Directory Federation Services (ADFS).
Basically, it seems that you need to control what a user can do at a more granular level than based only groups. Group membership can sometimes be very broad. For example, not every one in the "Users" might have the same right, not everyone in the "Sales" would have the same access. But then you don't want to create groups such as "Sales - Managers", "Sales - Employees", "Sales - Executives" etc. etc. This quickly becomes unwieldy. And no matter how much time you put into designing the perfect distribution of groups, in a few years it will all change because some subset of the sales managers will be allowed to do something, which other sales managers cannot.
To get around this problem, Claims based authentication is used. Rather than specifying rights at the group membership level you just check in your code whether a user has a certain "Claim". You can go nuts and create as many claims as makes sense for your application. You can have claims like "Can Change Birth Date", "Can Authorize Payment More Than $1000" etc. etc.
The claims are just attached to your user's identity, which is available via the thread's current principle.
Now, how does the user get assigned these "Claims" you ask? Well, if you are using ADFS, anyway you want. You can obviously do it based on AD group memberships. You can do it based on database look ups. You can do it on the time of the day or the month of the year if you so wish.
The point is, now your claim issuing and claim enforcement are completely independent and can change independently without affecting each other. Your code just says "Hey, this guy has a claim that lets him make more than $1000 payments, so I will let him do that. Why he has that claim, I don't know or care". Then your ADFS can issue claims based on any criteria that it sees fit. For example "If user is member of Managers group or has an entry in SuperUsers table in the security Database or is named 'Tim Timsky', he is allowed to spend more than $1000"
So to answer your question about "thinking only on group level which limits my options", it most certainly doesn't have to. If you are starting a new, green fields project, new tools like ADFS would give you a lot of options more easily.
But of course it comes with a caveat, which is that all abstraction has a cost of increased complexity. It is another part you are introducing into your system. You can decouple your application and introduce higher layers of abstraction and functionality. But whether or not that layer is worth introducing depends on how you plan to use the application. If you think that the application will never ever ever have to distinguish between a "Manager" and a "User" then, claims based authentication is an over kill. But if you feel that as time goes on, you will have different bits and pieces of functionality in your application that will need to be assigned to different users based on vague and ever changing rules, then claims based authentication will make your solution much neater.
As always, the net advantage of decoupling two parts depends on how often one changes independent of the other.
We've developed simple CRM application in ASP.NET MVC. It's for a single organization with few user accounts.
I'm looking for easy way to make it work with many organization. May I use ApplicationId from Membership provider for this? Every organization would have they own ApplicationId.
But this means that every row in the database would have to have ApplicationId too, right?
Please give you suggestions. Maybe there is a better way?
Unfortunately, for the "easy way" you already missed the bus. Since the easy way would have been to make this possible already by design. It would have not been that much of a burden to include the OwnerId to the data already in the first phase and make your business logic to work according to that.
Currently the "easy way" is to refactor all your data and business logic to include the OwnerId. And while doing it, look ahead. Think of the situations "what if we need to support this and that in the future" and leave some room there for the future by design. You don't need to fully implement everything right now but you'll find it out how easy it is to make your application scale if it was designed to scale.
What comes to the ApplicationId, that's an internal ID for your membership provides to scope your membership data per application. I would stay away from bleeding that logic to the whole of your application. Keep in mind that authenticating your web users and assigning them in roles and giving them rights through roles is a totally different process than ownership of data.
In ASP.NET MVC, you would use [Authorize] attribute to make sure that certain actions can or cannot be performed by certain users or groups while determining which data is whose, should be implemented in the data itself. Even if you would run two or more instances of your application, it'd still be the same application. So ApplicationId doesn't work here for scoping your data.
But, let's say your CRM would not be so small after all in the future and it becomes apparent that either your initial organization or one of the later ones would like to allow their customers to log on and check their data, you would need to build another application for the customers to log onto. This site would use a different applicationId than your CRM. Then your client organization could map the user accounts to their CRM records so that their customer could review them.
So, since your CRM is (still) small, the easiest way is to design a good schema for your clients to be stored in and then mark all your CRM data with an OwnerId. And that OwnerId cannot come from the users table, or membership table or anywhere near there. It has to come from the table that lists the legal owners of the data. Whether you want to call them Organizations, Companies, Clients or whatever. It cannot be userId, roleId, applicationId etc, since users might be leaving an owning organization, roles are shared between the organizations (at least the ones that are used to determine access to certain MVC actions) and applicationIds are meant for scoping membership and roles between different kinds of client applications.
So what you are missing here is the tables describing owners for the CRM records and mapping all the data to their owners. And for that there's no easy way. You already went on developing the CRM thinking "this is just a simple one-organization CRM so let's make things the easy". Now you're having a "simple multi-organization CRM and asking an easy way to recover from that initial lack of design. Next step would be asking how you make your "not so simple multi-organization CRM" to easily do something you didn't take in to account in the first place.
The easy solution is to design your application scalable and doing "just a little" extra to support future growth. It'll be much easier in the long run than to spend a lot of extra rewriting your application twice a year. Also, keep in mind. It's a CRM after all, and you can't go ahead and tell whoever is using it in their business that have a day off since we're fixing some stuff in the CRM.
I'm not patronizing you here. I'm answering to anyone who might be reading this to stop searching for easy solutions to recover from inadequate planning. There isn't any. And seeking one is making the same mistake twice.
Instead, grab some pen and paper and plan a workable design and make it work. Put some extra effort in the early stages of software design and development and you'll find that work saving you countless hours later in the process. That way, whoever is using your CRM will stay happy using it. It'll become easier to talk to your users about future changes while you don't have to think "I don't want to do that since it'd break the application again". Instead, you can enjoy together brainstorming the next cool step. Some of the ideas will be left for later but some room for implementation will be designed already on this stage so that the actual implementation year later will come in smoothly and will be enjoyable for all the parties involved.
That's my easy solution. I have 15 years of development behind and the fact that I'm still enjoying it to back the above up. And it's mainly because I take every (well most of them anyway) challenge as an opportunity to design the code better instead of trying to dodge the inevitable process. We have this old saying in Finland: "Either you'll do it or you'll cry doing it". And it fits the bill here perfectly. It's up to you if you like crying so much and take "the easy way" now.
I am looking into building an authentication in my ASP.NET application with the following requirements.
A user has exactly one Role (i.e. Admin, SalesManager, Sales, ....)
A role has a set of permissions to CRUD access a subset of existing objects. I.e.
"Sales has CREAD, READ, WRITE permission on object type "Products" but not DELETE"
Somehow I like the permissions to be in a hierarchy with inheritance so that I for i.e. Admin don't need to specify all available objects.
The system must quickly be able to answer the question "Does user X have permission to do Y to object Z"
All database managed (MSSQL), implemented in C#/ASP.NET
I would like to get feedback on these requirements? Any ideas how to implement this using ASP.NET framework(as much as possible)? (However, I'm also interested to know how this can be achieved without Memberships)
I think what you need to do here is implement a set of permissions query methods in either your business objects or your controller. Examples: CanRead(), CanEdit(), CanDelete()
When the page renders, it needs to query the business object and determine the users authorized capabilities and enable or disable functionality based on this information. The business object can, in turn, use Roles or additional database queries to determine the active user's permissions.
I can't think of a way to declaratively define these permissions centrally. They need to be distributed into the implementation of the functions. If you want do improve the design, however, you could use dependency injection to insert authorizers into your business objects and thus keep the implementations separate.
There's some code that uses this model in Rocky Lhotka's book. The new version isn't in Google yet.
I think one of the best implementations that I think will fulfill your requirements is documented here. The only issue is that this hooks into NHibernate, but you can use this as a template to create your own permissions implementation and simply hook into your own event model rather than that of NHibernates Interceptors.
I am working on such a system myself and will blog it once I am happy with it.
The membership API provided since ASP.NET 2.0 should suit your requirements well. The only thing I'm afraid it doesn't directly support is hierarchical roles. However you can easily use normal role based security with another manually written hierarchical roles table to achieve the required things.
You can read on how to set up ASP.NET Membership here: http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx
It allows you to group folders / pages etc into Groups / Users. I think you will find this sufficient!
The hiarchy is easily managed by extending the generated databases and procedures.
I would build the user/role relationship so users can have more than 1 role. I see a 1-1 relationship and I get nervous because I know that even if we don't see a need for it now, someone is someday going to want someone to be both a Sales user and a Customer Service user.
In our customer system, we use roles to layer on stuff like "delinquentCustomer." That way, the original permissions are still valid--as soon as they pay their bill. Worth considering this approach.