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
This commit is contained in:
Florent Vilmart
2017-07-25 15:26:34 -04:00
committed by GitHub
parent 7e54265f6d
commit 92d51def6b
3 changed files with 45 additions and 12 deletions

View File

@@ -71,6 +71,10 @@ describe('AuthenticationProviers', function() {
}); });
var createOAuthUser = function(callback) { var createOAuthUser = function(callback) {
return createOAuthUserWithSessionToken(undefined, callback);
}
var createOAuthUserWithSessionToken = function(token, callback) {
var jsonBody = { var jsonBody = {
authData: { authData: {
myoauth: getMockMyOauthProvider().authData myoauth: getMockMyOauthProvider().authData
@@ -81,18 +85,27 @@ describe('AuthenticationProviers', function() {
headers: {'X-Parse-Application-Id': 'test', headers: {'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest', 'X-Parse-REST-API-Key': 'rest',
'X-Parse-Installation-Id': 'yolo', 'X-Parse-Installation-Id': 'yolo',
'X-Parse-Session-Token': token,
'Content-Type': 'application/json' }, 'Content-Type': 'application/json' },
url: 'http://localhost:8378/1/users', 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 => { it("should create user with REST API", done => {
createOAuthUser((error, response, body) => { createOAuthUser((error, response, body) => {
expect(error).toBe(null); expect(error).toBe(null);
var b = JSON.parse(body); var b = body;
ok(b.sessionToken); ok(b.sessionToken);
expect(b.objectId).not.toBeNull(); expect(b.objectId).not.toBeNull();
expect(b.objectId).not.toBeUndefined(); expect(b.objectId).not.toBeUndefined();
@@ -118,14 +131,14 @@ describe('AuthenticationProviers', function() {
var objectId; var objectId;
createOAuthUser((error, response, body) => { createOAuthUser((error, response, body) => {
expect(error).toBe(null); expect(error).toBe(null);
var b = JSON.parse(body); var b = body
expect(b.objectId).not.toBeNull(); expect(b.objectId).not.toBeNull();
expect(b.objectId).not.toBeUndefined(); expect(b.objectId).not.toBeUndefined();
objectId = b.objectId; objectId = b.objectId;
createOAuthUser((error, response, body) => { createOAuthUser((error, response, body) => {
expect(error).toBe(null); expect(error).toBe(null);
var b = JSON.parse(body); var b = body;
expect(b.objectId).not.toBeNull(); expect(b.objectId).not.toBeNull();
expect(b.objectId).not.toBeUndefined(); expect(b.objectId).not.toBeUndefined();
expect(b.objectId).toBe(objectId); 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) => { it("unlink and link with custom provider", (done) => {
var provider = getMockMyOauthProvider(); var provider = getMockMyOauthProvider();
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);

View File

@@ -1185,10 +1185,7 @@ describe('Parse.User testing', () => {
expect(fileAgain.url()).toMatch(/yolo.txt$/); expect(fileAgain.url()).toMatch(/yolo.txt$/);
}).then(() => { }).then(() => {
done(); done();
}, error => { }).catch(done.fail);
jfail(error);
done();
});
}); });
it("log in with provider twice", (done) => { it("log in with provider twice", (done) => {

View File

@@ -297,7 +297,14 @@ RestWrite.prototype.handleAuthData = function(authData) {
} }
}); });
const hasMutatedAuthData = Object.keys(mutatedAuthData).length !== 0; 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 // Login with auth data
delete results[0].password; delete results[0].password;
@@ -328,10 +335,10 @@ RestWrite.prototype.handleAuthData = function(authData) {
// Just update the authData part // Just update the authData part
return this.config.database.update(this.className, {objectId: this.data.objectId}, {authData: mutatedAuthData}, {}); 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 // Trying to update auth data but users
// are different // are different
if (userResult.objectId !== this.query.objectId) { if (userResult.objectId !== userId) {
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
'this auth is already used'); 'this auth is already used');
} }