From 839a1172461bc51217e22e4bd3e10a83b03306d4 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Mon, 11 Sep 2017 09:52:18 -0400 Subject: [PATCH] Fixes #2885 duplicate sessions (#4143) * Adds test to repro the issue * Improved test * Destroy duplicate sessions for User/Installation-id pair - Sessions will also be created with action login instead of signup when using 3rd party auth --- spec/ParseUser.spec.js | 30 ++++++++++++++++++++++++++++++ src/RestWrite.js | 16 +++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index fbf7adf9..2e3b3705 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -1168,6 +1168,36 @@ describe('Parse.User testing', () => { }); }); + it('only creates a single session for an installation / user pair (#2885)', done => { + Parse.Object.disableSingleInstance(); + const provider = getMockFacebookProvider(); + Parse.User._registerAuthenticationProvider(provider); + Parse.User.logInWith('facebook', { + success: () => { + return Parse.User.logInWith('facebook', { + success: () => { + return Parse.User.logInWith('facebook', { + success: (user) => { + const sessionToken = user.getSessionToken(); + const query = new Parse.Query('_Session'); + return query.find({ useMasterKey: true }) + .then((results) => { + expect(results.length).toBe(1); + expect(results[0].get('sessionToken')).toBe(sessionToken); + expect(results[0].get('createdWith')).toEqual({ + action: 'login', + authProvider: 'facebook' + }); + done(); + }).catch(done.fail); + } + }); + } + }); + } + }); + }); + it('log in with provider with files', done => { const provider = getMockFacebookProvider(); Parse.User._registerAuthenticationProvider(provider); diff --git a/src/RestWrite.js b/src/RestWrite.js index 69944253..d2495e0e 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -568,7 +568,7 @@ RestWrite.prototype.createSessionToken = function() { objectId: this.objectId() }, createdWith: { - 'action': 'signup', + 'action': this.storage['authProvider'] ? 'login' : 'signup', 'authProvider': this.storage['authProvider'] || 'password' }, restricted: false, @@ -578,8 +578,18 @@ RestWrite.prototype.createSessionToken = function() { if (this.response && this.response.response) { this.response.response.sessionToken = token; } - var create = new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData); - return create.execute(); + + // Destroy the sessions in 'Background' + this.config.database.destroy('_Session', { + user: { + __type: 'Pointer', + className: '_User', + objectId: this.objectId() + }, + installationId: this.auth.installationId, + sessionToken: { '$ne': token }, + }); + return new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData).execute(); } // Handles any followup logic