Skip to content

Commit 73b0f9a

Browse files
fastrdeacinader
authored andcommitted
Merge pull request from GHSA-8w3j-g983-8jh5
* Add Test and Authenticator for GHSA-8w3j-g983-8jh5 * fix for GHSA-8w3j-g983-8jh5 * nit whitespace not sure why lint isn't catching...
1 parent 050dd19 commit 73b0f9a

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

Diff for: spec/ParseUser.spec.js

+37
Original file line numberDiff line numberDiff line change
@@ -3847,4 +3847,41 @@ describe('Parse.User testing', () => {
38473847
}
38483848
);
38493849
});
3850+
3851+
it('should validate credentials first and check if account already linked afterwards (GHSA-8w3j-g983-8jh5)', async done => {
3852+
// Add User to Database with authData
3853+
const database = Config.get(Parse.applicationId).database;
3854+
const collection = await database.adapter._adaptiveCollection('_User');
3855+
await collection.insertOne({
3856+
_id: 'ABCDEF1234',
3857+
name: '<some_name>',
3858+
email: '<some_email>',
3859+
username: '<some_username>',
3860+
_hashed_password: '<some_password>',
3861+
_auth_data_custom: {
3862+
id: 'linkedID', // Already linked userid
3863+
},
3864+
sessionToken: '<some_session_token>',
3865+
});
3866+
const provider = {
3867+
getAuthType: () => 'custom',
3868+
restoreAuthentication: () => true,
3869+
}; // AuthProvider checks if password is 'password'
3870+
Parse.User._registerAuthenticationProvider(provider);
3871+
3872+
// Try to link second user with wrong password
3873+
try {
3874+
const user = await Parse.AnonymousUtils.logIn();
3875+
await user._linkWith(provider.getAuthType(), {
3876+
authData: { id: 'linkedID', password: 'wrong' },
3877+
});
3878+
} catch (error) {
3879+
// This should throw Parse.Error.SESSION_MISSING and not Parse.Error.ACCOUNT_ALREADY_LINKED
3880+
expect(error.code).toEqual(Parse.Error.SESSION_MISSING);
3881+
done();
3882+
return;
3883+
}
3884+
fail();
3885+
done();
3886+
});
38503887
});

Diff for: spec/helper.js

+20
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ const defaultConfiguration = {
118118
},
119119
auth: {
120120
// Override the facebook provider
121+
custom: mockCustom(),
121122
facebook: mockFacebook(),
122123
myoauth: {
123124
module: path.resolve(__dirname, 'myoauth'), // relative path as it's run from src
@@ -348,6 +349,24 @@ function range(n) {
348349
return answer;
349350
}
350351

352+
function mockCustomAuthenticator(id, password) {
353+
const custom = {};
354+
custom.validateAuthData = function(authData) {
355+
if (authData.id === id && authData.password.startsWith(password)) {
356+
return Promise.resolve();
357+
}
358+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'not validated');
359+
};
360+
custom.validateAppId = function() {
361+
return Promise.resolve();
362+
};
363+
return custom;
364+
}
365+
366+
function mockCustom() {
367+
return mockCustomAuthenticator('fastrde', 'password');
368+
}
369+
351370
function mockFacebookAuthenticator(id, token) {
352371
const facebook = {};
353372
facebook.validateAuthData = function(authData) {
@@ -406,6 +425,7 @@ global.jequal = jequal;
406425
global.range = range;
407426
global.reconfigureServer = reconfigureServer;
408427
global.defaultConfiguration = defaultConfiguration;
428+
global.mockCustomAuthenticator = mockCustomAuthenticator;
409429
global.mockFacebookAuthenticator = mockFacebookAuthenticator;
410430
global.jfail = function(err) {
411431
fail(JSON.stringify(err));

Diff for: src/RestWrite.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -449,17 +449,10 @@ RestWrite.prototype.handleAuthData = function(authData) {
449449
let results;
450450
return this.findUsersWithAuthData(authData).then(async r => {
451451
results = this.filteredObjectsByACL(r);
452-
if (results.length > 1) {
453-
// More than 1 user with the passed id's
454-
throw new Parse.Error(
455-
Parse.Error.ACCOUNT_ALREADY_LINKED,
456-
'this auth is already used'
457-
);
458-
}
459452

460-
this.storage['authProvider'] = Object.keys(authData).join(',');
453+
if (results.length == 1) {
454+
this.storage['authProvider'] = Object.keys(authData).join(',');
461455

462-
if (results.length > 0) {
463456
const userResult = results[0];
464457
const mutatedAuthData = {};
465458
Object.keys(authData).forEach(provider => {
@@ -543,7 +536,15 @@ RestWrite.prototype.handleAuthData = function(authData) {
543536
}
544537
}
545538
}
546-
return this.handleAuthDataValidation(authData);
539+
return this.handleAuthDataValidation(authData).then(() => {
540+
if (results.length > 1) {
541+
// More than 1 user with the passed id's
542+
throw new Parse.Error(
543+
Parse.Error.ACCOUNT_ALREADY_LINKED,
544+
'this auth is already used'
545+
);
546+
}
547+
});
547548
});
548549
};
549550

0 commit comments

Comments
 (0)