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

beforeSave Parse.User: after facebook sign up clears attributes. #880

Closed
DrBeak1 opened this issue Mar 7, 2016 · 29 comments · Fixed by #952
Closed

beforeSave Parse.User: after facebook sign up clears attributes. #880

DrBeak1 opened this issue Mar 7, 2016 · 29 comments · Fixed by #952

Comments

@DrBeak1
Copy link

DrBeak1 commented Mar 7, 2016

I've been trying to get this to work for two days and can't seem to get things correct, so I suspect there is a bug somewhere.

I'm running parse-server on heroku connected to mongoDB. All is well.

I have a beforeSave setup so that when a new user is created I assign a few variables to them before saving to the db.

When I sign up via Facebook the beforeSave function is called, but all of the user object data is stripped except for ACL, updatedAt, createdAt, and username (which is a random string because of sign up via Facebook). The users auth data does not make it through and is therefore lost. Then if I sign up again using the same Facebook account, instead of logging in, it creates a brand new user. I've found that I can fix this issue by removing the beforeSave. With no beforeSave the auth data makes it to the database and future login attempts connect me to that previously created user (instead of creating new users each time). However, even with a beforeSave that is simply:

Parse.Cloud.beforeSave(Parse.User, function(request, response) {
         for (var k in request.object.attributes) {
                console.log(k+": " + `request.object.attributes[k]);`
         }
        response.success(request.object);
});

... where I'm not doing anything but logging the incoming attributes, all attributes are stripped except for the ones mentioned above.

Anyone else seeing this issue? I'm using parse-server, heroku, mongoLab, and an iOS client.

ALSO:
If I bypass the beforeSave, successfully creating the user - any time I try to modify the users attributes, I get an error "cannot modify user <objectId>", where <objectId> is the id of the user who is supposedly logged in.

More Research (Edit: regarding this piece, had to access vars via object.attributes.email):
If I JSON.stringify(request), the vars do come into the beforeSave correctly:

{"triggerName":"beforeSave","object":{"email":"mymail@me.com","username":"mymail@me.com","firstName":"Harry","lastName":"Houdini","randomId":"61fa3xxxxxxxxxx","objectId":"gIOxxxxxxx"},"master":false,"original":{"objectId":"gIOxxxxxxx"}}

But when I try to access the vars (request.object.email), I get nothing but undefined.

And More [2016-03-07, 10:36PM]:
Last one for tonight. I can see that auth data is being returned by Facebook after login via FB. I can confirm this by modifying the PFFacebookMobileAuthenticationProvider.m file to log the data returned from:

[PFFacebookPrivateUtilities userAuthenticationDataFromAccessToken:result.token];

on line 62 of that file. I can also see that after this login, that the access_token logged here does not match the access_token stored on my user in mongoDB, so this information is never being updated in the db. Clearly this is an issue. Now, why?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 8, 2016

Looking through RestWrite.js I think I see where the 'cannot modify user ...' error is coming from:
https://github.com/ParsePlatform/parse-server/blob/master/src/RestWrite.js#L769
This is in alignment with what I suspect is happening, that is: when logging in via Facebook auth data is not being stored, or it is, but a session token is not being linked/saved.

@rsweny
Copy link

rsweny commented Mar 9, 2016

I saw the error "cannot modify user" as well in 2.1.3 and I still see it in 2.1.4. I do have a beforeSave trigger as well. I'm using parse-server, heroku, mongoLab, and an Android client.

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 9, 2016

@rsweny , thanks for chiming in. I was starting to wonder if this was an iOS only problem (and hence perhaps an issue only with the ios cocoapod). pares-server 2.1.5 was just released; I haven't had a chance to test against it yet. I Plan to do so tonight.

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

Same issue with parse-server 2.1.5 :(

@flovilmart
Copy link
Contributor

in the beforeSave, the object should be a Parse.Object, therefore, you should access it's properties with object.get('prop');

if you just do response.success() without the request.object in it, what does it do?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

I was actually calling response.success() originally when I discovered the issue. It was only through more research that I found some threads suggesting that you had to return the object now. Neither iteration seems to make any difference.

@flovilmart
Copy link
Contributor

And without the beforeSave it's all good in the database?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

@flovilmart I can see the attributes there. That was a mistake on my part. However, the sessionToken and auth data are not making it there, no. Not in either case (with or without beforeSave).

That said, as of now the auth token I see in xcode is the same as the one stored on mongoDB, but I know it's not being updated because my user object was last updated 2 days ago.

Where the beforeSave came into play was at one point having the beforeSave in place was causing a new user to be created every time I tried to log in, even when using the same fb account. There seems to be two separate issues developing here; maybe connected, but unclear at this point. Sorry I realize this may sound a bit confusing.

@flovilmart
Copy link
Contributor

it is indeed very confusing, also, hard to reproduce on our side...

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

In any case - I really appreciate your attention, and appreciate you supporting the server framework.

Stepping back from everything and starting with what seems to be at the root of one of the issues: After facebook auth, the user is not updated on mongoDB - that is, the new session token and facebook auth data is not sent and stored. I can confirm this as true because immediately following a successful call to logInInBackgroundWithReadPermissions I try to fetch the users details fetchInBackgroundWithBlock. This results in: Object not found. (Code: 101, Version: 1.12.0), which is either (a) object doesn't exist (which it definitely does) OR (b) invalid session token.

@flovilmart
Copy link
Contributor

How is your parse-server configured for Facebook? did you set the appId there?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

I'm running locally now because I was tired of pushing builds to heroku for testing:

var api = new ParseServer({
  databaseURI: 'mongodb://pathToMyMongoDB',
  cloud: '/absolute/path/to/my/cloud/code/main.js',
  appId: 'ParseAppID',
  clientId: 'ParseClientID',
  masterKey: ParseMasterKey',
  facebookAppIds: ['MyFacebookAppId'],
  serverURL: 'http://localhost:1337/parse'
});

@flovilmart
Copy link
Contributor

And I assume the fbappid is valid. When you login with Facebook, you confirm that nothing happens, no user ID returned, no session token in the result?

@flovilmart
Copy link
Contributor

Also, as you're running locally, you could dig deeper in RestWrite.js this is where the Oauth handling happen. Maybe a function exits early, or there is an unreported error.

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

@flovilmart when I login with facebook I DO get userId, sessionToken, and authData. That's the weird thing. All of that data is connected to the user object that is returned by the call to logInInBackgroundWithReadPermissions. But when I try to do anything with that user (fetch or update) I get errors. When I look at the user info on mongoDB the data is not the same.

I thought that maybe it was creating new users, but the objectID connected to the returned user is the same. I'll dig into RestWrite - I'm not nearly as seasoned with node as I am ios but I'll see what I can come up with.

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

After playing around with logging in RestWrite.js for the last hour I can see two things:

  1. Each time I try to log in, it looks as though a new User is instantiated, but never added to the db.
  2. A new Session is created and assigned to that newly instantiated user and IS added to the db.

In the end I'm left with an orphaned Session object.

From my logs in function RestWrite(config, auth, className, query, data, originalData):

className: _Session
query:
data:::
sessionToken: r:374c545b0b548431a430785e0eeb6928
data:::user:::
__type: Pointer
className: _User
objectId: IydoFerQS3
user: [object Object]
createdWith: [object Object]
restricted: false
installationId: undefined
expiresAt: [object Object]

Above you see that a Session object is being created whose User property has an ID of IydoFerQS3. That Session object has a sessionToken property of r:374c545b0b548431a430785e0eeb6928.

If I go to mongoDB I can do a search for a Session where _session_token equals the above. This successfully finds the Session object, with it's user.objectId property set to IydoFerQS3. The Session is created successfully! Although the field is "_p_user": "_User$IydoFerQS3" instead of a user_id ... maybe just how the data is stored and related ... idk.

If I go to mongoDB and do a search for a User where _id equals IydoFerQS3 it returns nothing. The user is never created. But why would it be? This is a log in! Now, what determines whether or not to create a new User during log in with facebook?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

OK after a lot of trailing this thing I know what is happening, still unsure why, but I know what is happening. As mentioned above, the Session object that gets created at login is given an incorrect userId. I tracked this thing the entire way from RestWrite, through the DatabaseController, and back to RestWrite.

I can confirm this is happening because if I take the Session that is created and change its _p_user to the correct objectId, everything starts to work. I can update the user and it's owned objects.

Also, if you go to the handleOAuthAuthData function in RestWrite you'll see that whoever wrote it has a TODO that says 'does this handle re-linking correctly?' -- I can answer that question: No.

UPDATE 12:14 AM: Have to stop for now. I can see that when I try to login the auth.user object passed to RestWrite is undefined. I suspect that because there is no object there a new user is instantiated and then associated with the new Session object. What gets passed back is the new Session assigned to the wrong user, and the correct user. So you end up in a state where you are logged in with an incorrect sessionToken.

@flovilmart
Copy link
Contributor

@DrBeak1 can you try with the branch mentioned in the open PR?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 10, 2016

@flovilmart yep. I'm at 'work' now, may be able to get it in during lunch. Otherwise, it won't be until this evening. When I go to open PRs I see 11 of them ... are you referring to #952?

@flovilmart
Copy link
Contributor

Yes, that one.

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 11, 2016

@flovilmart I'm having trouble figuring out how to build against your pull request. I cloned the branch but I cant sort out how to point my dependency at it. Any tips?

@flovilmart
Copy link
Contributor

use npm link parse-server /path/to/my/parse-server

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 11, 2016

Thanks! I'm still trying to hash things out. I'm getting:

module.js:339
    throw err;
    ^

Error: Cannot find module 'parse-server'
    at Function.Module._resolveFilename (module.js:337:15)
    at Function.Module._load (module.js:287:25)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at Object.<anonymous> (/Users/drbeak1/Projects/remote-repos/myapp-heroku/server/app.js:2:19)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:457:10)

Once I get things working I'll let you know what I find.

@flovilmart
Copy link
Contributor

uhm.. did you do the npm link thing?

let' say you clone parse-server in:

cd /Users/drbeak/Projects
git clone https://github.com/parseplatform/parse-server
git checkout flovilmart.OAuthImprovements
cd /Users/drbeak1/Projects/remote-repos/myapp-heroku/server/
npm link parse-server /Users/drbeak/Projects/parse-server
npm install

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 11, 2016

I don't know what is going on now. Once I linked it to the cloned branch I started getting that error. Now I cannot do anything without getting errors. Sorry, I'm not sure what is happening.

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 11, 2016

Ugh, OK - that was frustrating. I had to totally delete the local environment and start from scratch.

@flovilmart Looks like things are working now. I can log in using facebook, log out, log in using standard email/pw with a different user, log out, then log in again with facebook. From what I can tell, what ever you did fixed the issues I was seeing. I can also see all the correct data coming through in my beforeSave method.

I just wish that I had another user to test against who had previous Facebook authData stored (pre- switching to a self hosted parse-server). I'm worried that there may still be issues there, but I have no way of testing it personally. For now, I'd say this issue is fixed. Maybe @rsweny can test against your build and see if it fixes things for him?

@flovilmart
Copy link
Contributor

Ok nice!
Good to know that the fix is working! So we can close that one?

@DrBeak1
Copy link
Author

DrBeak1 commented Mar 11, 2016

Unless @rsweny wants to test beforehand - if not, yep - go ahead and close. Things seem to be working. If that changes I can create another issue and reference this one if it seems related.

Thanks again!

@yonahforst
Copy link

I'm having a similar issue. @DrBeak1, How did you delete your local environment? I'm getting that same error Error: Cannot find module '../lib/cli/parse-server'

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

Successfully merging a pull request may close this issue.

4 participants