Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse.FacebookUtils.Link from Cloud Code fails yet works on Parse.com #1464

Closed
steven-supersolid opened this issue Apr 12, 2016 · 7 comments
Closed

Comments

@steven-supersolid
Copy link
Contributor

The following code will work on Parse.com with JS SDK 1.6.14, but not in a parse-server unit test:

it('respects useMasterKey when linking with Facebook', (done) => {
    var user = new Parse.User();
    user.setUsername('username');
    user.setPassword('password');
    user.set('attribute', 'value1');
    user.signUp().then((user) => {
      Parse.User.logOut();
      var authData = {
        id: "8675309",
        access_token: "jenny",
        expiration_date: new Date().toJSON()
      };
      return Parse.FacebookUtils.link(user, authData);
    }).then((user) => {
      done();
    }, (error) => {
      fail(error.message);
      done();
    });
  });

I'm not sure that this should work on Parse.com because it would enable one user to link another user's account.

I would expect the following code to work correctly in both cases but this will require a change to Parse-SDK-JS:

      return Parse.FacebookUtils.link(user, authData, {
        useMasterKey: true
      });

Just wanted to discuss here before creating an issue in the JS SDK and probably a PR.

@flovilmart
Copy link
Contributor

You can easily test that unit test by calling

Parse.initialize(appId, jsKey, masterKey);
Parse.serverURL = 'https://api.parse.com/1';

with appId, jsKey and masterKey real keys to parse.com

@drew-gross
Copy link
Contributor

it would enable one user to link another user's account

Wouldn't it only allow them to link one account they one to another account they either own or have write access to?

@steven-supersolid
Copy link
Contributor Author

OK, so running that specific test against Parse.com gives an error message: Parse::UserCannotBeAlteredWithoutSessionError and there is no concern about a user being able to add their FB authdata to another account.

The problem I'm trying to debug is where I call Parse.FacebookUtils.link from Cloud Code. This succeeds on Parse.com but not in parse-server

exports.testFacebookLink = function(request, response) {
    Parse.Promise.as().then(
        function() {
            return Parse.FacebookUtils.link(request.user, request.params.authData);
        }
    ).then(
        function(result) {
            response.success(result);
        },
        function(error) {
            response.error(error);
        }
    );
};

I'll keep digging to see if I can provide any more details.

The error code is:
error: code=206, message=cannot modify user cuaTkv6i5Z

Here's how I'm testing:

curl -X POST \
-H "X-Parse-Application-Id: XXX" \
-H "X-Parse-REST-API-Key: YYY" \
-H "X-Parse-Session-Token: r:ZZZ" \
-H "Content-Type: application/json" \
-d '{"authData":{"access_token": "insertFBToken","expiration_date": "2016-06-11T12:53:32.000Z","id": "FBAppId"}}' \
https://api.parse.com/1/functions/TestFacebookLink

@steven-supersolid steven-supersolid changed the title Parse.FacebookUtils.Link fails when not logged in yet works on Parse.com Parse.FacebookUtils.Link from Cloud Code fails yet works on Parse.com Apr 12, 2016
@steven-supersolid
Copy link
Contributor Author

The error code is thrown in Parse-SDK-JS ParseUser.linkWith as the authData does not contain a session token so the user cannot save.

  linkWith(user: ParseUser, authData: AuthData) {
    return user.save({ authData }).then(() => {
      if (canUseCurrentUser) {
        return DefaultController.setCurrentUser(user);
      }
      return user;
    });
  }

authData is coming from the user.

    value: function _linkWith(provider, options) {
      var _this = this;

      var authType;
      if (typeof provider === 'string') {
        authType = provider;
        provider = authProviders[provider];
      } else {
        authType = provider.getAuthType();
      }
      if (options && options.hasOwnProperty('authData')) {
        var authData = this.get('authData') || {};
        authData[authType] = options.authData;

        var controller = _CoreManager2['default'].getUserController();
        return controller.linkWith(this, authData)._thenRunCallbacks(options, this);
      }

Perhaps parse-server lacks the full auth data on request.user?

I could not see any significant difference in request.user with parse-server by logging JSON.stringify(request.user) in the Cloud Code function.

Parse.com
{"authData":{"anonymous":{"id":"xxx"}},"createdAt":"2016-04-13T09:25:03.377Z","deviceId":"customAttribute","secret":"customAttribute","sessionToken":"r:yyy","updatedAt":"2016-04-13T09:25:04.081Z","username":"zzz","objectId":"1eR2mhyb8u"}

parse-server
{"ACL":{"1eR2mhyb8u":{"read":true,"write":true}},"deviceId":"customAttribute","updatedAt":"2016-04-13T09:25:04.081Z","createdAt":"2016-04-13T09:25:03.377Z","username":"zzz","authData":{"anonymous":{"id":"xxx"}},"secret":"customAttribute","sessionToken":"r:yyy","objectId":"1eR2mhyb8u"}

Adding logging to the linkWith function above, the authData at this point on parse-server is :
{ anonymous: { id: 'xxx' }, facebook: { access_token: 'aaa', expiration_date: '2016-06-11T12:53:32.000Z', id: 'bbb' } }

@steven-supersolid
Copy link
Contributor Author

I can think of 3 solutions so far:

  1. Change parse-server so that request.user (in Cloud Code) includes authentication data
  2. Change Parse.FacebookUtils.link() to support useMasterKey as an option (so can still be used in Cloud Code)
  3. Don't support Parse.FacebookUtils.link() in Cloud Code

I could live with 3. but am worried what else is not going to work if we do not fix 1. E.g. Consider users with a limited ACL with no public read, only self-read/write. The following Cloud Code fetches the user making the call:

Parse.Cloud.define('TestFetch', function(request, response) {
    return request.user.fetch().then(
        function(result) {
            response.success(result);
        },
        function(error) {
            response.error(error);
        }
    );
});

Call with:

curl -X POST \
-H "X-Parse-Application-Id: xxx" \
-H "X-Parse-REST-API-Key: yyy" \
-H "X-Parse-Session-Token: r:eca1c844s4560525274880d5c624af2b" \
-H "Content-Type: application/json" \
-d '{}' \
https://api.parse.com/1/functions/TestFetch

On Parse.com the response is:
{"result":{"__type":"Object","authData":{"anonymous":{"id":"5b49ada2-4df5-4457-8ea4-21550cf07a92"}},"className":"_User","createdAt":"2016-04-14T10:59:14.102Z","deviceId":"customAttribute","objectId":"IeFIqWGE0I","secret":"customAttribute","sessionToken":"r:eca1c844s4560525274880d5c624af2b","updatedAt":"2016-04-14T10:59:14.936Z","username":"S0v11rLgxRHa2o3RtB87keUEm"}}

With a local parse-server pointing to the same database:
{"error":"unauthorized"}

@steven-supersolid
Copy link
Contributor Author

Possibly related: #1090. Will investigate further.

@steven-supersolid
Copy link
Contributor Author

I've solved this as suggested in the other ticket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants