I am developing a CMS like application using MVC 3 (RC2) and I am in crossroads at this point. I am unable to convince myself if my proposed approach is appropriate or not. I guess it is because I am aware that I am trying to cut some corners which will cost me heavily later down the line.
I will get right down to describing my problem:
1) I have a resource (lets call it A) which has to be made editable.
2) I have a custom permission system implemented which has 2 (of many) permissions:
Can Edit Own Resource
Can Edit Other Resource
3) Creator of resource A is free to edit it if they have 'Can Edit Own Resource' permission.
4) A separate user can only edit A if they have permission 'Can Edit Other Resource'
Now that the requirement is described, let me tell you my approach so far:
1) I have a controller called 'ResourceController'
2) I have a action called 'Edit'
3) The action has a attribute on it: [CustomerAuthorize(Perm.CanEditOwnResource, Perm.CanEditOtherResource, Any = true)]
4) I have a service class which takes care of domain validation.
So a user get call the action method if they have either the 'Can Edit Own Resource' or 'Can Edit Other Resource' permission.
How do I decide (and where should this decision be made) on whether the user has the right permission or not (depending on whether they own the resource?) Should it be in the controller action, in the resource service class, in a separate service class?
Waiting to hear different views...
Because of the nature of MVC, you will want to have your authentication checks at a variety of points.
For one, you'll need to be able to display visual cues on the UI (i.e. show the edit button or not show it), so the logic will have to be made available to your Views.
Of course, that's only for UI purposes. You'll want authentication/authorization on your controller actions as well, just in case someone goes around your UI to access it.
Finally, the most secure place to authenticate and authorize an action is right before you perform it. If you have a handler, for example, I would place some authorization logic there. You want to make sure that no one can write around your security logic by calling the service from somewhere else, and not knowing that there were restrictions on that service. This helps make the security options more granular as well.
One way to approach it is to have 2 actions, instead only "Edit", you have "EditOwnResource" and "EditOtherResource". You can then place a single permission on each of these.
Then if you are using the MVVM pattern you can bind the availability of these actions to wether it is an ownResource or otherResource. The setting of these values is done in the view model.
Related
I find myself too many times in front of a situation when I should create two different resources on an API server, that are initiated by one single action. I would call it cross-controller opertaion: an operation that requires logic to be performed in two different controllers
For example, imagine an applicaiton with a User model and an Account model
User can be associated to multiple accounts.
In my REST API I have an /accounts/ endpoint and a /users/ endpoint which are responsible for the Account and User model respectively, and /accounts/:account_id/users endpoint for the assocation between these 2 models
So if a user choose to disassociate itself from an account I make such a request: HTTP DELETE /accounts/:account_id/users/:id
When a user registers I obiously POST /users/ to create a new user
There is also an option for a user to register and get directly associated to an account (by a special invitaion for example). In such case I would have to register a user and create an association to the account being invited to, preferably doing that in a single request to the server.
I know I can do a request to /users/ in order to create the user and then another request to /accounts/1/users/1 to create the link between the user and the account, but doing so only to stick to the REST principles seems redundant.
Another option is to create a different action such as register_from_invitation that will take care of both action but then the question is where it should sit. In the AccountUsers controller, in the Users controller or in the Accounts controller. This also seems wrong to me.
Any prefered way to solve such a design issue?
I can see several possible solutions.
The method that you described (making to requests: first to /users and second to /accounts/...) is the most REST-full. It is simple, logical and used widely. It may look a little awkward, but it's not. Here you split your logic strictly, not mixing up methods from two controllers.
Then, you can always accept requests to POST /accounts/:account_id/users/. And here create a new user and bind it to the account. From the outer space of your app it looks good, but inside it will cause a slight mix of User and Account methods in Account controller. That's no good.
If you still want to have register_by_invitation method, you can confidently put it in Users controller. Create user there and bind it to some Account you receive in request params.
However, if you want to keep your app RESTfull and do not want to mix the logic from several controllers into one, there's only one I see.
Consider adding another resource called UserAccountMembership. The benefit of this is that you'll separate responsibilities: User and Account resources will remain clean, and at the same time you'll get a resource where you expose specific information about a "connection" between those two (like date/time of a link creation, active/inactive status etc.):
/useraccountmemberships/{useraccountmembershipid} POST, PUT, GET, DELETE
{
"Id": useraccountmembershipid,
"UserId": userid,
"AccountId": accountid,
"Timestamp": "2018-1-1",
...
}
You may still want to allow access to memberships via a parent resource, which is fine:
/users/{userid}/useraccountmemberships GET
/accounts/{accountid}/useraccountmemberships GET
RoR4 app. I have a page X which shows pricing stuff in an eCommerce website. So there is a pricing controller with index page showing the pricing content. There is a purchase button which needs to do following things:
If clicked, check whether the user is authenticated
If authenticated, take them to third party services for credit card information
On successful purchase, redirect the flow back to original eCommerce site
My dilemma:
Should I add a new purchase controller? or add a new method purchase in existing controller of pricing.
It all depends whether you want your app to be RESTful or not. Even if your pricing controller currently has only index action, in the future you might want to create a new/edit actions (to add prices), and therefore corresponding create/update actions.
Of course, if you don't want to be RESTful then you can add whatever methods you want. However, I think it is just a good practice to follow RESTful pattern. Such design has well defined and recognized semantics, and also keeps you from cluttering your controllers.
So, if you decide to go with a purchase controller, I would advise you to do the following:
Use create action as the destination for your purchase button.
On that create action add a before_action filter that will check for authentication.
Here I am not sure how exactly your interface with the third party is done, but I suggest you to record into your database all the important information about your transaction/purchase with some key, and only then execute your third-party purchase call.
On successful or unsuccessful purchase, hopefully, you can ask your third-party to redirect back to the update action in your purchase controller where you can update your record from step 3 with the return information (I prefer to save the whole response body too), and then depending on the status redirect internally to your pricing page in case of success or to some error processing page.
I am not saying that it is the only possible solution. However, from my previous experience I learned that keeping detailed transaction log in your own database is very useful for troubleshooting issues in the future.
So, the final answer is to prefer a separate controller over adding an unRESTful method that does not exactly fit to your existing controller.
I believe it is good to have another controller because the name of the controller is pricing controller which I think not much tells the concern about the payments or transactions.
how about having new controller as payments_controller.rb or transactions_controller.rb
pricing name itself indicates some price related stuff where payments or transactions name indicates more close purpose of the functionality.
In my application users are able to transfer points between them. In my view, I check if user can transfer points from his account, if he can, I render something that allows him to do that. I would not like to check that again in my controller, so I need some mechanism, that will allow me to check if user that I rendered a viewpage for, is the same as the one that is sending a request to my controller.
So basically, I would like to check in my controller, if currently logged user is the same as the one that sent the request - and to do this, I think that I need something that works similar to ViewBag, but not from the controller to a view, but from view to a controller. Is that possible?
A proper way to do this will not be the transfer of such information between user requests. Every request shall be stateless but you trying to embed a state. This is a fair way to shoot yourself in a foot.
If your action requires authentication (you are who you say you are) you should do it using standard classic ASP net way. This will embed a standard authentication token to any further user requests. This way you will know that the user is authenticated or not.
For some actions that require authorisation (user has permissions to perform an action) you must validate that a user has the power to perform such action. This must be done for every request and it is usually a fast operation. No need to optimise things here by reducing your security barrier.
If you search for authentication and authorisation with classic asp, you will get a more fine grained answer on how to do the coding bit.
I wouldn't recommend, but you can still embed hidden information with
<input type="hidden" value="..."/>
So I read about how implementing your own authorization routines are bad!
http://www.nashcoding.com/2011/02/05/using-the-forms-authentication-membership-provider-on-appharbor/
And I got scared, because I've been implementing my actions as such (example, preventing access to account details if authenticated user is not the logged in user)
public ActionResult DisplayAccount(int someid){
Account a = context.Accounts.Single(a => a.id == someid);
// currentUserId() returns userid from FormsAuthentication
if (!a.owner == currentUserId()){
/* Not Authorised! */
}
}
Which apparently means it will break if ASP decides to cache my action (so the action doesn't even get executed).
So I'm now looking into using AuthorizeAttribute to do what I need to do, which is
prevent access to an action if not authenticated
check if authenticated user has access to the retrieved resource
However whenever I think about it, I can't think about how to implement the 2nd point. Roles don't work because its on a site wide level, but within the application there users have roles as well (e.g. Owner, Moderator, Contributor, User etc.), and they only have these roles within their respective parts of the application (e.g. owner of thread, contributor to wiki, moderator of forum etc.)
I have run into several examples of overriding AuthorizeCore. I can sort of imagine creating multiple AuthorizeAttribute subclasses for each resource I have (luckily not many), But just by looking at it, does that mean I have to query the database everytime I hit that action to ensure that the logged in user should be able to access that data, then query the database in my action to get the model, instead of doing that in my query?
So my questions are
am I getting too worried about caching too much? Will any of the following happen
website caches user A details, which is rendered on user B's screen?
website caches admin version of a page (with edit controls), and normal user sees cached version?
Using AuthorizeAttribute is a given, but how do I achieve what I need to do in point 2 without having to hit the database prior to the Action? Or what is the best way to achieve it in any case.
Or do I only use AuthorizeAttribute to determine if the user is logged in, and do other checking logic in my action?
Anyway, I hope this post isn't treading on any old paths (I couldn't find anything on this that I found definitive)
Edit: I guess, if I don't enable caching this problem wouldn't occur, is this correct?
Edit: for now, I am going to going to use vanilla AuthorizeAttribute, then check resource level access in my actions, then make sure I don't use caching for any authenticated actions. Hopefully will get more answers for this over the week.
I used the following approach in a recent project, by creating a DataRightsAttribute that used an enumeration for each supported model type. It works by first extracting the id from the route data, formcollection or querystring. Then it queried up the model type determined by the enum, and did the appropriate check to see if the current user is authorized to access it.
Usage was like this:
[DataRights(ModelType.Customer)]
This was used alongside AuthorizeAttribute (which we overrided), and never noticed any problems with caching.
I'm required to provide functions for both users and administrators to edit account and profile details in a web application. An example of a URL for the public side of these profiles is:
http://example.com/user/joe
I'm still torn between two ways to design these URLs. I've thought of either this:
http://example.com/user/joe/edit
Or something non-specific and separate to the profiles:
http://example.com/account
The benefit of the first one is that it allows administrators to do their job through the same functions. This avoids building a whole different backend specifically for administrators. I suppose the negative here is that I'd have to be careful with authorization and make sure nobody can edit what they are not supposed to edit.
The second is a more standard way of doing things, it'd turn out to be simpler and easier to secure, though it means a separate interface for administrative users.
What is SO's opinions on this? Are there any more pros/cons for either way? Which method would you recommend to use?
I would have a different view for the administrator with such a security sensitive area. It makes things much more explicit having a separate view. It is likely even an administrator would only be able to edit certain user information and thus have a different view to the user editing themselves.
It makes the authorization much clearer even if the two views shared a common edit form
If you are using an MVC approach, then my suggestion would be:
http://example.com/user/edit/1234
or
http://example.com/user/edit/joe
Where user is the controller, edit the controller method and 1234 or joe the user id or username respectively.
But as Gumbo commented, administrators should not be allowed to edit user information. They should have some mecanism to disable the account in case of a profile has offensive content or false info. Forcing the user to update it to get the account active again.
The way we do it is the admin and the user share the same view. Items which are admin-only are protected from editing or viewing by the user.
The reason for the single view is:
It reduces the number of 'moving parts' - when a new field is added to the user screen, it only needs to be added once,
It is easier to move items to/from the user's purview. If all of a sudden, management decides to allow a user to manage their "FizzBar" then we only need make the change in one place, and
It is easier to segregate the roles and the functions at the controller level.
I think that you should go with the second approach. It's more secure and flexible, and shouldn't be harder to code than profile editing the profile inline.