restrict create/update/delete to requests with a user only - parse-platform

In Parse.com client APIs, it is possible to perform create/update/delete on object of any class. It would be good to set a minimal level of security that restrict these operations only to requests that are made by a Parse.User. This way, someone with access to say your REST or JS key can't just spam create or delete a ton of objects in your database.
I have 2 working solutions but they seem a tad too complicated for something so simple. If you know of a simpler way to accomplish this on Parse.com, please let me know.
Solution 1: Create a RegularUser role and assign all your users that role. Set up class level permission to this role. Undefined users (from requests made without a user) naturally do not have this role, thus access is revoked.
Solution 2: Create beforeSave and beforeDelete cloud code for every class and reject all requests without a user.
I'm pretty new to Parse and I have a feeling that I've missed a simple setting somewhere that lets you lock down your data for logged in users only. Please point that out if that is the case. If you are experienced in Parse.com and in your experience, there is no simpler way, I'd appreciate the confirmation as well. Thanks

I'm answering this a bit late, but I thought I would answer to help out other readers. Like Akshay pointed out, you should definitely set the appropriate Class Level Permissions. But I think what you were getting at can be addressed through ACLs, as suggested by the Parse docs: https://www.parse.com/docs/ios/guide#security-access-control-lists
You can set different types of ACLs for each class, or if you only want to allow users to access their own objects, it's really easy to implement that across all classes:
To make it super easy to create user-private ACLs for every object, we
have a way to set a default ACL that will be used for every new object
you create:
In Swift for iOS:
PFACL.setDefaultACL(PFACL(), withAccessForCurrentUser: true)
I have this set up in my app's AppDelegate, which has the effect that any object the user creates can only be read/updated/deleted by that user.

Related

Restful API: Best practice for admin and user scope

I am building an API where users and admins can interact with the same data, but with different needs.
A user can also have access to the admin panel, if he has the "admin" role.
Let's see for example we have a resource like Badges. A Badge is simply a reward when you achieve some actions into the app.
GET http://localhost/api/v1/badges
An authenticated user can call this endpoint and it returns the list of all badges, if they have it or not, with progress details.
GET http://localhost/api/v1/badges?user_id=2
with user_id parameter, we can see these details of another user (if he allows it).
But from the admin scope, I just need to see the list of all badges, without achievement details (CRUD operations).
So I have 2 options in mind:
Create "admin" endpoints: GET http://localhost/api/v1/admin/badges.
Adding custom header "X-App-Scope" to identify if I am in admin or user.
I don't like the second one because I think I will have so many if statements and behavior in the same endpoint, depending of the scope.
Because I have lots of use cases like this, I want to make sure my API architecture is good to handle user/admin needs.
Do you guys have any idea/example to manage stuff like this?
Thanks!
My personal preference is to separate admin API routes from user ones. i.e. having two routes
/api/v1/badges
/api/admin/v1/badges
You will have two unique documentation, one for each route, which makes it easier to maintain and understand
It will be easier to tell the difference between the user and the admin versions
There is no need extra code to check for request headers or url params.
It makes your middleware less complicated, especially if authentication and permissions are handled there.
It is more scalable for teams as there is only one kind of request and response format per API.
TL;DR: REST is designed in the expectation that you would use two different resources here.
The core problem is this: how would a general purpose component, like a browser, know that your special resource needs to have this custom header added?
In particular, consider the case where I send to you a copy of the URL for this resource, and nothing else. How are you to know to add the customer header to the request?
On the other hand, if you use different resources to share this information with each audience, everything just works.
The only way I found to stay as simple/clear as possible is to make multiple endpoints, for each use case:
GET http://localhost/api/v1/badges to get all badges in raw data
GET http://localhost/api/v1/users/badges to get all badges with user stats (progression, achievement...) in a transformed format
GET http://localhost/api/v1/users/{uuid}/badges to get all badges with user stats (progression, achievement...) in a transformed format for the specified user, if his profile is public
Now I have a lot of /users/XYZ endpoints, but my code seems easier to read & maintain, and I don't really need to see the code to guess what data will be returned, the conditions, etc...
I keep wondering how the other APIs are written when you have an admin section, because having /users everywhere isn't really "pretty", and I don't see that anywhere else.

ASP.NET Web API 2 - State & Static Scope

I am a relatively inexperienced programmer.
I have managed to build a web api which uses basic authentication as per the following:
https://weblog.west-wind.com/posts/2013/Apr/18/A-WebAPI-Basic-Authentication-Authorization-Filter which is working very nicely (forced over ssl obviously). Inside the OnAuthorizeUser i check the un/pw against an mssql database, via a call to an internal class called "DB" where all my database interaction occurs.
So all Controller methods are filtered by the Basic Authentication ("decorated" at the Controller level) however, access to certain Controller Methods also needs to be limited depending on the user - so there is a need to understand the user permissions. Based on my limited former ASP.NET experience I think I would have stored the relevant user details in a Session (or possibly cache) however I have so far steered clear of this based on wanting to stick to the concept of having a RESTful application etc
Rightly or wrongly, in playing around I realised I could use a private static (instance?) of my User class inside my internal DB class and populate it at the time of initial authorisation. I also added a public method (public User getThisUser()) to return the private User. From within my Controller methods I create an instance of DB and am able to check the values etc.
I was very worried that I would have issues with the "scope" of this "static" User, so to test, I created a Controller method to simply return the User information from DB.getThisUser(). In doing so I have found that I can log in as multiple different users (using different browsers concurrently for example) and each one consistently returns the correct user information (as logged in).
I'm still not entirely convinced this is "safe" however reading through the details of implementing something like ASP.NET Identity as a possible alternative makes my head spin and really seems like massive overkill in this case - I'm not using Entity Framework and after much searching I could not find a single example of NOT using an ORM (I need a solution to work with an existing DB).
Is this destined to fail? Do I go back to considering session or cache? Something else? I would really appreciate any feedback / advice on this from all of you who are more experienced than me. Thanks in advance for any help.
i think you're getting a bit confused.
an API is supposed to be stateless, meaning no session. Yes, you have a controller which translates into an endpoint.
You can hit an endpoint with all the information required to satisfy the request and this is it. Don't think of an API as an actual application where all requests are linked somehow. Instead, think of it at an application where each request is separate and can come from anywhere and any user.
How does the application know which user sent a request? Well, it doesn't unless you pass that information in.
You don't fire a request saying GetMeUserDetails. The api has no idea what you want. Instead you would say GetMeUserDetails for userId 12345. Now, since your request contains all the information required to satisfy the request, the API can now give you what you expect.
If some calls require authentication, you might use some sort of tokens to identify the user, but again, the information is passed in via the token.
You probably realize what static means and how it works. you are not going to see problems until you try to send two or more requests at the same time and then you'll realize that the first call now contains the details of the second request because well, static ...

Allow admin user to login as other users

Is there any way to login other users account for admin user ?
Currently authentication based on Meteor Accounts
I saw this post but didn't working at all now.
The feature is important for us because when user have problem in system then admin need to see it this by simulating user account.
Thanks in advance.
It seems you want to impersonate a user. This means that you want to have Meteor.userId (or this.userId depending on context) reflect the _id of a specific user both on the client and the server.
afaict the only way to do this is to login as the user. Presumably you don't want to ask the user for their password so you have a couple of choices:
Save their existing password, replace it (temporarily) with a password of your choosing, then after you're done impersonating their account, restore their existing password.
You probably don't want to ask the user for their password and you don't need to. All you need to do is set aside Meteor.user.findOne(userId).services.password.bcrypt, then reset the password to your temporary value, then restore the original bcrypt value later.
The downside is that the original user would not be able to login while you are logged-in. Plus it's really hacky.
Extend Meteor's Accounts package to provide impersonation capability in a more elegant manner.
You might also look at validateLoginAttempt. The docs are unclear as to whether a failed login attempt could be overridden with a successful one but if it could then that would provide another pathway to solve your problem.
Instead of logging in as the users, which requires their password and which is a total no-no, you may use rather alanning:roles and allow the admin to assign the role of any user in order to draw views based the user's role.
This requires a well designed role system.
As a plus you could then at least load the documents associated with the user who you want to support.
This requires a well designed document and data model.
But generally spoken you should rather focus on writing good tests (test driven development) for components as unit tests, integration tests and UI tests.
This will reduce the need to manually view the app as an end user a lot.
The most common end user problems can be reduced by creating a good knowledge base like a wiki or video tutorials.
Even if then an error occurs in the end user side, I would rather try to implement a well designed error log that allows users automatically create tickets on error which also include the error stack.
All the above methods are to be favored before logging in AS THE USER.
As #Jankpunkt has already mentioned alanning-roles I can add something you can use without installing any external package.
Just keep a type key in the profile object of the users collection. Then define some types like 1 for super-admin, 2 for admin, 3 for general etc. Then check the authorisation of particular action by checking the value of user.profile.type key.
Caveats: Make sure you are checking the type in server side. By default profile field is writable from the client end, so if you are putting type field in the profile object make sure that you are not allowing users to modify users collection in the client end.
Here is how to restrict client end update in users collection:
Meteor.users.deny({
update() { return true; }
});
Read more on roles and permissions here:
https://guide.meteor.com/accounts.html#roles-and-permissions

Confusion with the Django permission system

Django comes with a simple permissions system. It provides a way to assign permissions to specific users and groups of users. Like this: 'app_lable.model_name'. It may be convenient for the django admin, but I think it will be use difficult when I use it to control what people can to do with it.
For example, If I want to control whether a certain user can post a comment or see some portion content of my site. I have to config a permission group to him, but why not just add a user property like can_post or can_view_certain_portion? Its seems more intuitive.
So who can help me understand those things? Thanks in advance.
The reason to keep permissions in a separate model is to leverage groups.
So if you needed to change the permissions on many users at once you could simply update the permissions of the group they are assigned to.
Also since users can belong to more than one group you have more flexibility for customizating permissions per user.
Keep in mind vanilla django permissions are model based so if you need to limit changing only certain fields to different users you will need something more robust like django-guardian.

Combining classes in Anypic example project

I was going through the Anypic tutorial and the data model part specifically because I want to build a similar app. My question is why can't I remove the permission restrictions and let the image class hold the likes (int) and the comments (array of strings) and don't allow the users of the app to edit other users images. What can be the drawbacks of this approach?
Thank you
The permission restrictions are in place for security.
By separating the likes from the Photo class, it prevents other users from modifying someone else's photos. The way Parse ACLs (Access Control Lists) work is by restricting read/write access.
Let's consider the scenario that likes are contained within the Photo class. If one user wants to like someone else's photo, they will have to modify the user's photo directly, which requires write permissions in the ACL.
No big deal, right? Wrong. Someone with malicious intent could structure their own REST API calls to your app and perform whatever actions they want on other people's photos. I could remotely modify or delete your photos, spoof additional likes, and tons of other exploits depending on the rest of your app.
If you still wanted to keep likes within the Photo class, but not have public write access, then whenever someone tries to like a photo, you would have to perform the write in cloud code using the master key. You would also need to do extra validation beforehand so someone else couldn't spoof this request.
Parse ACLs are great because they are incredibly simple and quickly allow you to compartmentalize read/write access as needed within your app.

Resources