Skip to content

Commit

Permalink
Merge pull request from GHSA-8w3j-g983-8jh5
Browse files Browse the repository at this point in the history
* Add Test and Authenticator for GHSA-8w3j-g983-8jh5

* fix for GHSA-8w3j-g983-8jh5

* nit whitespace

not sure why lint isn't catching...
  • Loading branch information
fastrde authored and acinader committed Jul 10, 2019
1 parent 050dd19 commit 73b0f9a
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 10 deletions.
37 changes: 37 additions & 0 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3847,4 +3847,41 @@ describe('Parse.User testing', () => {
}
);
});

it('should validate credentials first and check if account already linked afterwards (GHSA-8w3j-g983-8jh5)', async done => {
// Add User to Database with authData
const database = Config.get(Parse.applicationId).database;
const collection = await database.adapter._adaptiveCollection('_User');
await collection.insertOne({
_id: 'ABCDEF1234',
name: '<some_name>',
email: '<some_email>',
username: '<some_username>',
_hashed_password: '<some_password>',
_auth_data_custom: {
id: 'linkedID', // Already linked userid
},
sessionToken: '<some_session_token>',
});
const provider = {
getAuthType: () => 'custom',
restoreAuthentication: () => true,
}; // AuthProvider checks if password is 'password'
Parse.User._registerAuthenticationProvider(provider);

// Try to link second user with wrong password
try {
const user = await Parse.AnonymousUtils.logIn();
await user._linkWith(provider.getAuthType(), {
authData: { id: 'linkedID', password: 'wrong' },
});
} catch (error) {
// This should throw Parse.Error.SESSION_MISSING and not Parse.Error.ACCOUNT_ALREADY_LINKED
expect(error.code).toEqual(Parse.Error.SESSION_MISSING);
done();
return;
}
fail();
done();
});
});
20 changes: 20 additions & 0 deletions spec/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const defaultConfiguration = {
},
auth: {
// Override the facebook provider
custom: mockCustom(),
facebook: mockFacebook(),
myoauth: {
module: path.resolve(__dirname, 'myoauth'), // relative path as it's run from src
Expand Down Expand Up @@ -348,6 +349,24 @@ function range(n) {
return answer;
}

function mockCustomAuthenticator(id, password) {
const custom = {};
custom.validateAuthData = function(authData) {
if (authData.id === id && authData.password.startsWith(password)) {
return Promise.resolve();
}
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'not validated');
};
custom.validateAppId = function() {
return Promise.resolve();
};
return custom;
}

function mockCustom() {
return mockCustomAuthenticator('fastrde', 'password');
}

function mockFacebookAuthenticator(id, token) {
const facebook = {};
facebook.validateAuthData = function(authData) {
Expand Down Expand Up @@ -406,6 +425,7 @@ global.jequal = jequal;
global.range = range;
global.reconfigureServer = reconfigureServer;
global.defaultConfiguration = defaultConfiguration;
global.mockCustomAuthenticator = mockCustomAuthenticator;
global.mockFacebookAuthenticator = mockFacebookAuthenticator;
global.jfail = function(err) {
fail(JSON.stringify(err));
Expand Down
21 changes: 11 additions & 10 deletions src/RestWrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,17 +449,10 @@ RestWrite.prototype.handleAuthData = function(authData) {
let results;
return this.findUsersWithAuthData(authData).then(async r => {
results = this.filteredObjectsByACL(r);
if (results.length > 1) {
// More than 1 user with the passed id's
throw new Parse.Error(
Parse.Error.ACCOUNT_ALREADY_LINKED,
'this auth is already used'
);
}

this.storage['authProvider'] = Object.keys(authData).join(',');
if (results.length == 1) {
this.storage['authProvider'] = Object.keys(authData).join(',');

if (results.length > 0) {
const userResult = results[0];
const mutatedAuthData = {};
Object.keys(authData).forEach(provider => {
Expand Down Expand Up @@ -543,7 +536,15 @@ RestWrite.prototype.handleAuthData = function(authData) {
}
}
}
return this.handleAuthDataValidation(authData);
return this.handleAuthDataValidation(authData).then(() => {
if (results.length > 1) {
// More than 1 user with the passed id's
throw new Parse.Error(
Parse.Error.ACCOUNT_ALREADY_LINKED,
'this auth is already used'
);
}
});
});
};

Expand Down

0 comments on commit 73b0f9a

Please sign in to comment.