From a39d045c7dd6f6a4e1f997981bcb11e8bceecdcd Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Mon, 18 Sep 2017 14:53:11 -0400 Subject: [PATCH] Fixes issue #4150: Session management (#4152) * Adds tests * Provide fix * Fix post sessions (#4167) * add tests * provide fix * remove console.log --- spec/rest.spec.js | 94 +++++++++++++++++++++++++++++++++++++++++++++++ src/RestWrite.js | 14 ++++++- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/spec/rest.spec.js b/spec/rest.spec.js index bb0e21ac..5e2bf051 100644 --- a/spec/rest.spec.js +++ b/spec/rest.spec.js @@ -5,6 +5,7 @@ var Config = require('../src/Config'); var Parse = require('parse/node').Parse; var rest = require('../src/rest'); var request = require('request'); +var rp = require('request-promise'); let config; let database; @@ -498,6 +499,99 @@ describe('rest create', () => { expect(error.code).toEqual(119); done(); }) + }); + + it ('locks down session', (done) => { + let currentUser; + Parse.User.signUp('foo', 'bar').then((user) => { + currentUser = user; + const sessionToken = user.getSessionToken(); + var headers = { + 'Content-Type': 'application/octet-stream', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + }; + let sessionId; + return rp.get({ + headers: headers, + url: 'http://localhost:8378/1/sessions/me', + json: true, + }).then(body => { + sessionId = body.objectId; + return rp.put({ + headers, + url: 'http://localhost:8378/1/sessions/' + sessionId, + json: { + installationId: 'yolo' + } + }) + }).then(done.fail, (res) => { + expect(res.statusCode).toBe(400); + expect(res.error.code).toBe(105); + return rp.put({ + headers, + url: 'http://localhost:8378/1/sessions/' + sessionId, + json: { + sessionToken: 'yolo' + } + }) + }).then(done.fail, (res) => { + expect(res.statusCode).toBe(400); + expect(res.error.code).toBe(105); + return Parse.User.signUp('other', 'user'); + }).then((otherUser) => { + const user = new Parse.User(); + user.id = otherUser.id; + return rp.put({ + headers, + url: 'http://localhost:8378/1/sessions/' + sessionId, + json: { + user: Parse._encode(user) + } + }) + }).then(done.fail, (res) => { + expect(res.statusCode).toBe(400); + expect(res.error.code).toBe(105); + const user = new Parse.User(); + user.id = currentUser.id; + return rp.put({ + headers, + url: 'http://localhost:8378/1/sessions/' + sessionId, + json: { + user: Parse._encode(user) + } + }) + }).then(done).catch(done.fail); + }).catch(done.fail); + }); + + it ('sets current user in new sessions', (done) => { + let currentUser; + Parse.User.signUp('foo', 'bar') + .then((user) => { + currentUser = user; + const sessionToken = user.getSessionToken(); + const headers = { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + }; + return rp.post({ + headers, + url: 'http://localhost:8378/1/sessions', + json: true, + body: { 'user': { '__type': 'Pointer', 'className':'_User', 'objectId': 'fakeId' } }, + }) + }) + .then((body) => { + if (body.user.objectId === currentUser.id) { + return done(); + } else { + return done.fail(); + } + }) + .catch(done.fail); }) }); diff --git a/src/RestWrite.js b/src/RestWrite.js index 81ff4250..9415529c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -627,7 +627,7 @@ RestWrite.prototype.handleFollowup = function() { }; // Handles the _Session class specialness. -// Does nothing if this isn't an installation object. +// Does nothing if this isn't an _Session object. RestWrite.prototype.handleSession = function() { if (this.response || this.className !== '_Session') { return; @@ -644,6 +644,16 @@ RestWrite.prototype.handleSession = function() { 'ACL on a Session.'); } + if (this.query) { + if (this.data.user && !this.auth.isMaster && this.data.user.objectId != this.auth.user.id) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME); + } else if (this.data.installationId) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME); + } else if (this.data.sessionToken) { + throw new Parse.Error(Parse.Error.INVALID_KEY_NAME); + } + } + if (!this.query && !this.auth.isMaster) { var token = 'r:' + cryptoUtils.newToken(); var expiresAt = this.config.generateSessionExpiresAt(); @@ -661,7 +671,7 @@ RestWrite.prototype.handleSession = function() { expiresAt: Parse._encode(expiresAt) }; for (var key in this.data) { - if (key == 'objectId') { + if (key === 'objectId' || key === 'user') { continue; } sessionData[key] = this.data[key];