Parse-server: ParseUser.fetchInBackground() fails when _User CLP without public get permission

Created on 12 Oct 2020  路  5Comments  路  Source: parse-community/parse-server

I am using CLP to restrict access to the _User collection, essentially removing all permissions for the public except for create permission. This in my understanding means that anybody can sign up to create an account (POST to /users) but do nothing else unless they are logged in. They can not browse users, or get info about random user by trying to guess objectId and performing random GET /users/abcd for randomly generated abcd.

When the user is logged in (they send a valid X-Parse-Session-Token in the headers) they can GET /users/me to fetch info about their own user account successfully.

The user however can not currently perform GET /users/abc where abc is objectId of a user for which the user successfully obtained a session token via signup or login.

This can easily be demonstrated via iOS or Android SDK where a call to

ParseUser.getCurrentUser().fetchInBackground()

fails with:

error: Permission denied for action get on class _User.

I am sure this may be addressed by setting up proper ACL on the _User collection entries, but I still think the default behavior should be that ParseUser.getCurrentUser().fetchInBackground() should succeed for user for which I have a session token.

enhancement

Most helpful comment

After writing the past post, I did few tests and I see what you say. I believe we have an inconsistency here. The user is able to retrieve its own data through /classes/me (no matter the CLP in place), but not through /classes or /classes/objectId if the CLP is not public. I believe we should either allow or disallow for all of them and ensure consistency. @dplewis @mtrezza thoughts?

All 5 comments

For that to work as you expect, I believe you need to leave the CLP with read public access and the ACL without public read access and read access only set to the own user. You can do that through a beforeSave trigger. It is kinda confusing but, in order to access an object, the user must pass in the CLP rule AND also in the ACL rule. If you remove public access from CLP, you are explicitly saying Parse Server to not allow any user to read the objects of that class. An exception for the User class would bring even more complexity for the permission sets in my point of view.

After writing the past post, I did few tests and I see what you say. I believe we have an inconsistency here. The user is able to retrieve its own data through /classes/me (no matter the CLP in place), but not through /classes or /classes/objectId if the CLP is not public. I believe we should either allow or disallow for all of them and ensure consistency. @dplewis @mtrezza thoughts?

I have experimented a bit more with pointer based authentication, which I think works really great especially for data private to the user, where nobody except the user can read, browse, modify, delete. In such a configuration, simply providing a session token as part of the request automatically makes it possible via pointer authentication to read, browse, modify, and delete your own records. Which I think is great and expected from the API design and security perspective.

So inferring from these. I expect that just by providing the session token I should be able to read my own _User, my own _Installation objects and my own _Session objects. These are special cases as they by default do not provide any way to use pointer authentication, unless you explicitly attach a user to them?

I believe we should either allow or disallow for all of them and ensure consistency

I agree.

I expect that just by providing the session token I should be able to read my own _User, my own _Installation objects and my own _Session objects.

In principle yes, but restrictions should be possible on the field level because also an authenticated user can be malicious. I think an authenticated user should not be able to freely read, write, update, delete their User, Installation, Session object, whether that is via /classes or /me.

It does feel like this is inconsistent.

I feel like the fetch is doing a GET on the _User class, which is why it is being caught by the CLP. According to this, I feel like the fetch should really be doing a /parse/users/me, which should bypass the CLP.

We found a workaround using the sessionToken.

You can use the sessionToken to become the user again. This seems to use different logic that fits with the CLPs. You are essentially re-logging-in the user.

ParseUser.becomeInBackground("session-token-here", new LogInCallback() {
  public void done(ParseUser user, ParseException e) {
    if (user != null) {
      // The current user is now set to user.
    } else {
      // The token could not be validated.
    }
  }
});
Was this page helpful?
0 / 5 - 0 ratings