REST API logged in user can access data (parse.com) - rest

I'm using the parse REST API.
I need to setup so that for any requests made:
1) only logged in/authenticated users can Read or Write.
2) users can only access/modify records they own.
My current implementation:
1) using the Application key + REST API key.
2) sending request to user login endpoint, on success returning the user data including the session token
for 2), I'm not doing anything with the session token yet.
I understand that parse has:
1) class based permissions
2) object-level permissions (ACL's)
With Read and Write access on the class level, and by simply using the Application Key + REST API Keys,
anyone with these two keys can access that class (ofcourse, the Master Key has even more "power").
I want to simply say that they can Read and Write on the class level, if they're logged in/authenticated.
And when they Read, Update or Delete, they can only do so if they're owner of the object.
I assume that session token will play a role in the logged in part, and ownership is defined by object-level ACL
Is this correct and how to roughly set this scenario up in parse?
It's not clear to me in the REST API how to handle this (what I think is a common) type of scenario.
Thanks for any feedback

{"ACL":{"$CURRENT_USER":{"read":true,"write":true}}}
above in acl column will mean at the security level, only the creator has RW permissions. No other user can see these records with this ACL attr value regardless of their access on the CLASS level.
OR
you control the accessor predicates in your app. So you can add a column = 'createdBY' of type pointer_to_class_User.
Any queries just contain predicate ..
'where={"createdBy":{"__type":"Pointer","className":"User","objectId":"$CURRENT_USER"}}'
which enforces ( outside row security level ) idea of only getting result sets containing rows for the current-user.
all depends on how you want to use the security layer.
I would do it using the predicates and resort to the ACL only where you may have stuff like SSN's or Salary where as a policy you dont what general read permissions.

Related

How to design REST API with one action but two different meanings?

Given the example of a shop API with an orders resource. You would want to delete one order by id
DELETE /orders/:orderId
Under the hood you run an update query and set canceled to true. But what if
A customer calls this endpoint:
You need a canceledByCustomer database flag
No additional permissions are required
An administrator calls this endpoint?
You need a rejectedByAdministrator database flag
Additional permissions are required
Would you keep the endpoint posted above and check internally, if the calling user tries to cancel the order of another user and if true, this is a reject action?
Would you add two query parameters cancel and reject and one of them MUST be true and one of them MUST be null/false?
Would you violate the design rules, create two different endpoints and add verbs to them like so?
DELETE /orders/:orderId/cancel => customer can call it
DELETE /orders/:orderId/reject => only administrators can call it
Does someone know about the best practises for such "domain driven" problems?
API endpoints don't have to correlate on what happens closer to the core, for example in your Aggregate Root or CommandHandler. In my opinion, make the API routes as verbose as possible, which means creating their own separate routes for each use case. Push the logic on what database flag to use (canceledByCustomer vs rejectedByAdministrator) closer down to the entity.

how to isolate data in Restful API

There are some restful apis, as follows:
api/v1/billing/invoices/{invoiceNumber}
api/v1/billing/transactions/{transactionNumber}
And, each invoice or transaction belong to a specific account.
When implementing the restful apis, we must meet: Each account can only view their own invoice or transaction.
How should we isolate the data in restful apis?
Of course, we can pass the account number to the api, such as:
api/v1//billing/invoices/{invoiceNumber}?accoutNumber=XXX
api/v1/billing/{accountNumber}/invoices/{invoiceNumber}
But the Invoice Number has been able to uniquely identify a resource. So I do not want the problem to be complicated.
Is there any other way to solve this problem?
You are mixing a lot of things here.
This is not a REST problem, this is a security problem. More precisely, it's a OWASP top 10 2013 Insecure direct object vulnerability.
Let's make it simple: you have a URL like this
.../superSensitiveStuff/1
and you want to prevent the owner of "1" from accessing to ".../superSensitiveStuff/2"
To the best of my knowledge, there are three ways of dealing with this issue:
enforcing integrity in request URLs. This strategy does not apply to all cases, it only works in those scenarios where the client issues a request to a resource previously communicated by the server. In this case, the server may add a query param like this
.../superSensitiveStuff/1?sec=HMAC(.../superSensitiveStuff/1)
where HMAC is a cryptographic HASH function. If the parameter is missing, the server will drop the request and if it's there the server will be able to verify that it's exactly the authorized URL because the HMAC value guarantees its integrity(for additional infos, hit the link above).
using unpredictable references. The problem here is that a user can guess another id. "uhmm... I have the resource number 1, let me check whether the resource number 2 exists". If you drop sequences and move to long random number this is very hard to do. The resource will become
.../superSensitiveStuff/195A23FR3548...32OT465
This is good because it's effective and cheap.
exploiting a mixed RBAC-ABAC approach. RBAC stands for Role Based Access Control and this is what you are using. The leading A of the second acronym stands for Attribute. This means that access is provided on the basis of a user role and an attribute. In this case is the userId, since it must be authenticated for accessing private resources. In few words, when a user requests a specific .../superSensitiveStuff resource it is loaded from the repository when you have the ownership information for that resource. It could be a DB, for example, and your SuperSensitiveStuff java business model could be like this
public class SuperSensitiveStuff {
private String userId;
private String secretStuff;
...
}
now, in your controller you can do the following
String principal = getPrincipal(); //you request the logged userId
SuperSensitiveStuff resource = myService.load(id); //you load the resource using the {id} in the request path
if (resource.getUserId.equals(principal))
return resource //200 ok, this is an authorized access
else
throw new EvilAttemptException() //401 unauthorized, cheater detected

How to securize an entitie on Sails?

I'm developing an API with Sails, and now I need to securize some variables from an entity. Those variable will be accesed only from Admin or own user.
I have an structure like this:
Employee (contains your employee records)
fullName
hourlyWage
phoneNumber
accountBank
Location (contains a record for each location you operate)
streetAddress
city
state
zipcode
...
I need to encrypt phonenumber and accountbank, to avoid anyone to see the values of this fields in the DataBase. Only the owner or the admin.
How I can do that? Thanks
You are looking for a way to encrypt data so that people with no required access right could not see it.
The solution for that is not Sails.js specific and Node actually comes with tools to encrypt data :https://nodejs.org/api/crypto.html.
The key rule here is to always keep your secret password safe.
As for integration in your Sails.js application, I would use callbacks in Models. The official documentation provides a good example here : http://sailsjs.org/documentation/concepts/models-and-orm/lifecycle-callbacks
Basically you just define a function that will be called each time the record is about to be created, fetched or updated. You can then apply your encrypt/decrypt functions there.
This will encrypt/decrypt your phone numbers and bank account numbers automatically.
Regarding access control, you can use Sails' policies along with authentication to determine if the client has the right to access the resource. If not you can always remove attributes from the response sent back to the client.

REST API - filters, child entities or is leaking information really so bad?

The basic problem
I have a rest API. For the sake of this example, let's say I have users, they can be members in any number of groups, and both users and groups can own objects.
Any user can filter objects by various criteria:
/objects?color=green
/objects?created=yesterday
but only members of a given group can filter by group ownership:
/objects?groupId=1
and only the actual user can filter by user ownership:
/objects?userId=55
There are now two basic patterns - one could make the object a child entity of the group, such as:
/groups/4/objects/1
with 4 being the group ID and 1 being the object ID. the other option is having group and objects side-by-side:
/groups/4
and
/objects/1
making the object a child of the group and/or user would eliminate the other filtering options - essentially, i have one object with multiple paths to it.
The actual question
If I want to limit access for a regular user so that he/she can only access objects that are directly owned by him/her or by groups that he/she is a member of, it does work as a filter on the collection - but what about the entity level?
If I try:
/objects/9
But the object is owned by a group I am not a member of, I would expect an authorization error, while if the object doesn't exist at all, i would expect a "not found" - this, however, would leak information about the book's existence, and I also would have to retrieve the object in order to be able to determine whether or not the user has the right to see it.
So I came up with this:
/objects/9?groupId=4
or
/objects/9?userId=55
In this, I can base the initial decision on authorization on the group ID or user ID, and then try to retrieve the object with the additional restriction.
If the user is NOT a member of group 4, I can say not authorized, and if the book doesn't exist, I can say not found, meaning not that the object doesn't exist, but that the object doesn't exist in group 4. This answer is more clear, and also I would not have to retrieve the object first.
The alternative would be to return an authorization error regardless of whether it is due to the fact I am not authorized OR due to the fact that the object doesn't exist. This answer is slightly imprecise, but it would put less of a burden on the caller.
Another possibility would be to map multiple paths:
/objects
/groups/4/objects
/users/9/objects
/colors/green/objects
This seems rather messy and would violate the principle of having a single path for a single concept.
Does anyone have any practical insight on this? Any reasons (apart from the ones mentioned) why one or the other would be preferable?
If I understand you correct, every object is linked to (at least) one group or (at least) one user, so you don't have the problem of having an object without a group or user.
If this is the case I don't see the point in using filters as it would not make sense in a REST way and also not give any benefit to the client site.
So as you suggested you could just use the following:
/groups/$groupID/objects/$objectID
and
/user/$userID/objects/$objectID
Now you server should check if the client is authorized ("the user a member of the group" / "the current user") given the $groupID xor the $userID
if not authorized: not even check if object is there. Just give the not authorized error.
if authorized: give standard response codes
I don't see a benefit for a non authorized client to get information if a resource is available or not as its not important for him, because he cant access it either way. And as you suggested it would result in a information leak which could result in a security problem (but that is completely depending on your API and what its information and usage).
Now lets go through the scenarios for group calls:
User Arnold (member of groups: 1,2,3) wants to access existing object 7 of the member group 3.
GET /groups/3/objects/7
response: #200
User Arnold (member of groups: 1,2,3) wants to access non existing object 55 of his member group 2.
GET /groups/2/objects/55
response: #404
User Arnold (member of groups: 1,2,3) wants to access existing object 11 of a non member group 5.
GET /groups/5/objects/11
response: #401
User Arnold (member of groups: 1,2,3) wants to access non existing object 19 of a non member group 5.
GET /groups/5/objects/19
response: #401
And for user objects:
User Arnold wants to access his non existing object 56.
GET /user/arnold/objects/56
response: #404
User Arnold wants to access his existing object 13.
GET /user/arnold/objects/13
response: #200
User Arnold wants to access Jon's existing object 77.
GET /user/jon/objects/77
response: #401
User Arnold wants to access Jon's non existing object 88.
GET /user/jon/objects/88
response: #401
As you can see the server just responds with #401 if the client is non authorzied. Additional it would be great to give a error message in the body e.g. Sorry, but you are not authorized to see content of user "Jon" or Sorry, but you are not authorized to see content of group "ABYZX", so the client knows what the problem is.
This seems rather messy and would violate the principle of having a single path for a single concept.
I don't see it that way as also different sources (1) (3) and SO answers say its really no problem to have multiple paths or URIs.
Each resource in a service suite will have at least one URI identifying it.
It could help clients understand the authorization process and with that help them to navigate through your API.
Any of the URI choices you describe are fine. I perfer flat URIs, but it doesn't really matter.
The real question is how to handle unauthorized requests. In that case, I suggest responding with 404 in all cases including when the resource exists, but the user doesn't have access. It avoids the information leaking problem and it is completely compatible with the HTTP specification.
This pattern makes sense logically too. From the perspective of the user with insufficient permissions, the resource doesn't exist.
If you have ever tried to view a private Github project without having permissions to view it, you would have seen this pattern in action. Github will respond with 404 even if the project actually exists.

Resftul API structure, Is userID expected in route if already derived from session token?

I am currently planning a web API based on the principles of REST. I am using a session token to correct identify what user is making a request (after authentication of course), then determining if that user has access to the given resource.
Assuming the user making the request has a userID of 7, and I am wanting to retrieve a list of only the presentations that he can access, would best/proper practice be to:
1. Include my userID in the route, such as:
localhost:55555/api/users/7/presentations
or
2. Not include userID, such as:
localhost:55555/api/presentations
Each presentation can be accessed by any number of other users. For this reason I am leaning towards option 2 but would like to know what others think before I finalize the structure.
A very common pattern for REST APIs is to have both:
a list resource with optional parameters like /presentation/?by=Alice&since=2013-1-1,
object resources like /presentation/0AFF56E7.
For presentations, I wouldn't use a composite ID containing the user ID, since it doesn't seem really needed and it would prevent future features like changing the "owner" of the presentation (without changing its ID).