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...
This commit is contained in:
committed by
Arthur Cinader
parent
050dd19e80
commit
73b0f9a339
@@ -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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ const defaultConfiguration = {
|
|||||||
},
|
},
|
||||||
auth: {
|
auth: {
|
||||||
// Override the facebook provider
|
// Override the facebook provider
|
||||||
|
custom: mockCustom(),
|
||||||
facebook: mockFacebook(),
|
facebook: mockFacebook(),
|
||||||
myoauth: {
|
myoauth: {
|
||||||
module: path.resolve(__dirname, 'myoauth'), // relative path as it's run from src
|
module: path.resolve(__dirname, 'myoauth'), // relative path as it's run from src
|
||||||
@@ -348,6 +349,24 @@ function range(n) {
|
|||||||
return answer;
|
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) {
|
function mockFacebookAuthenticator(id, token) {
|
||||||
const facebook = {};
|
const facebook = {};
|
||||||
facebook.validateAuthData = function(authData) {
|
facebook.validateAuthData = function(authData) {
|
||||||
@@ -406,6 +425,7 @@ global.jequal = jequal;
|
|||||||
global.range = range;
|
global.range = range;
|
||||||
global.reconfigureServer = reconfigureServer;
|
global.reconfigureServer = reconfigureServer;
|
||||||
global.defaultConfiguration = defaultConfiguration;
|
global.defaultConfiguration = defaultConfiguration;
|
||||||
|
global.mockCustomAuthenticator = mockCustomAuthenticator;
|
||||||
global.mockFacebookAuthenticator = mockFacebookAuthenticator;
|
global.mockFacebookAuthenticator = mockFacebookAuthenticator;
|
||||||
global.jfail = function(err) {
|
global.jfail = function(err) {
|
||||||
fail(JSON.stringify(err));
|
fail(JSON.stringify(err));
|
||||||
|
|||||||
@@ -449,17 +449,10 @@ RestWrite.prototype.handleAuthData = function(authData) {
|
|||||||
let results;
|
let results;
|
||||||
return this.findUsersWithAuthData(authData).then(async r => {
|
return this.findUsersWithAuthData(authData).then(async r => {
|
||||||
results = this.filteredObjectsByACL(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 userResult = results[0];
|
||||||
const mutatedAuthData = {};
|
const mutatedAuthData = {};
|
||||||
Object.keys(authData).forEach(provider => {
|
Object.keys(authData).forEach(provider => {
|
||||||
@@ -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'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user