Skip to content

Fixes issue affecting linking users to a 3rd party auth #4047

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

Merged
merged 4 commits into from
Jul 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions spec/AuthenticationAdapters.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ describe('AuthenticationProviers', function() {
});

var createOAuthUser = function(callback) {
return createOAuthUserWithSessionToken(undefined, callback);
}

var createOAuthUserWithSessionToken = function(token, callback) {
var jsonBody = {
authData: {
myoauth: getMockMyOauthProvider().authData
Expand All @@ -81,18 +85,27 @@ describe('AuthenticationProviers', function() {
headers: {'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Installation-Id': 'yolo',
'X-Parse-Session-Token': token,
'Content-Type': 'application/json' },
url: 'http://localhost:8378/1/users',
body: JSON.stringify(jsonBody)
body: jsonBody,
json: true
};

return request.post(options, callback);
return new Promise((resolve) => {
request.post(options, (err, res, body) => {
resolve({err, res, body});
if (callback) {
callback(err, res, body);
}
});
});
}

it("should create user with REST API", done => {
createOAuthUser((error, response, body) => {
expect(error).toBe(null);
var b = JSON.parse(body);
var b = body;
ok(b.sessionToken);
expect(b.objectId).not.toBeNull();
expect(b.objectId).not.toBeUndefined();
Expand All @@ -118,14 +131,14 @@ describe('AuthenticationProviers', function() {
var objectId;
createOAuthUser((error, response, body) => {
expect(error).toBe(null);
var b = JSON.parse(body);
var b = body
expect(b.objectId).not.toBeNull();
expect(b.objectId).not.toBeUndefined();
objectId = b.objectId;

createOAuthUser((error, response, body) => {
expect(error).toBe(null);
var b = JSON.parse(body);
var b = body;
expect(b.objectId).not.toBeNull();
expect(b.objectId).not.toBeUndefined();
expect(b.objectId).toBe(objectId);
Expand All @@ -134,6 +147,22 @@ describe('AuthenticationProviers', function() {
});
});

it("should fail to link if session token don't match user", (done) => {
Parse.User.signUp('myUser', 'password').then((user) => {
return createOAuthUserWithSessionToken(user.getSessionToken());
}).then(() => {
return Parse.User.logOut();
}).then(() => {
return Parse.User.signUp('myUser2', 'password');
}).then((user) => {
return createOAuthUserWithSessionToken(user.getSessionToken());
}).then(({ body }) => {
expect(body.code).toBe(208);
expect(body.error).toBe('this auth is already used');
done();
}).catch(done.fail);
});

it("unlink and link with custom provider", (done) => {
var provider = getMockMyOauthProvider();
Parse.User._registerAuthenticationProvider(provider);
Expand Down
5 changes: 1 addition & 4 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1185,10 +1185,7 @@ describe('Parse.User testing', () => {
expect(fileAgain.url()).toMatch(/yolo.txt$/);
}).then(() => {
done();
}, error => {
jfail(error);
done();
});
}).catch(done.fail);
});

it("log in with provider twice", (done) => {
Expand Down
13 changes: 10 additions & 3 deletions src/RestWrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,14 @@ RestWrite.prototype.handleAuthData = function(authData) {
}
});
const hasMutatedAuthData = Object.keys(mutatedAuthData).length !== 0;
if (!this.query) {
let userId;
if (this.query && this.query.objectId) {
userId = this.query.objectId;
} else if (this.auth && this.auth.user && this.auth.user.id) {
userId = this.auth.user.id;
}
if (!userId || userId === userResult.objectId) { // no user making the call
// OR the user making the call is the right one
// Login with auth data
delete results[0].password;

Expand Down Expand Up @@ -328,10 +335,10 @@ RestWrite.prototype.handleAuthData = function(authData) {
// Just update the authData part
return this.config.database.update(this.className, {objectId: this.data.objectId}, {authData: mutatedAuthData}, {});
});
} else if (this.query && this.query.objectId) {
} else if (userId) {
// Trying to update auth data but users
// are different
if (userResult.objectId !== this.query.objectId) {
if (userResult.objectId !== userId) {
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
'this auth is already used');
}
Expand Down