From 92d51def6bdcd83931115592e07f74e6803683a0 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Tue, 25 Jul 2017 15:26:34 -0400 Subject: [PATCH] Fixes issue affecting linking users to a 3rd party auth (#4047) * Fixes issue affecting linking users to a 3rd party auth * Fixes problematic test * Better fix * nits --- spec/AuthenticationAdapters.spec.js | 39 +++++++++++++++++++++++++---- spec/ParseUser.spec.js | 5 +--- src/RestWrite.js | 13 +++++++--- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index 37763fcc..3294d6ec 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -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 @@ -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(); @@ -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); @@ -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); diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 32c505e0..69f3de62 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -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) => { diff --git a/src/RestWrite.js b/src/RestWrite.js index fffc7f91..199cd62f 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -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; @@ -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'); }