Skip to content

Commit 9d781c4

Browse files
mtrezzadplewis
authored andcommitted
Throw error when setting authData to null (#6154)
* added ignore authData field * add fix for Postgres * add test for mongoDB * add test login with provider despite invalid authData * removed fit * fixed ignoring authData in postgres * Fix postgres test * Throw error instead of ignore * improve tests * Add mongo test * allow authData when not user class * fix tests * more tests * add condition to synthesize authData field only in _User class it is forbidden to add a custom field name beginning with `_`, so if the object is not `_User` , the transform should throw * add warning log when ignoring invalid `authData` in `_User` * add test to throw when custom field begins with underscore
1 parent 1c8d4a6 commit 9d781c4

File tree

5 files changed

+125
-2
lines changed

5 files changed

+125
-2
lines changed

spec/MongoTransform.spec.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,46 @@ describe('parseObjectToMongoObjectForCreate', () => {
479479
}).toThrow();
480480
done();
481481
});
482+
483+
it('ignores User authData field in DB so it can be synthesized in code', done => {
484+
const input = {
485+
_id: '123',
486+
_auth_data_acme: { id: 'abc' },
487+
authData: null,
488+
};
489+
const output = transform.mongoObjectToParseObject('_User', input, {
490+
fields: {},
491+
});
492+
expect(output.authData.acme.id).toBe('abc');
493+
done();
494+
});
495+
496+
it('can set authData when not User class', done => {
497+
const input = {
498+
_id: '123',
499+
authData: 'random',
500+
};
501+
const output = transform.mongoObjectToParseObject('TestObject', input, {
502+
fields: {},
503+
});
504+
expect(output.authData).toBe('random');
505+
done();
506+
});
507+
});
508+
509+
it('cannot have a custom field name beginning with underscore', done => {
510+
const input = {
511+
_id: '123',
512+
_thisFieldNameIs: 'invalid',
513+
};
514+
try {
515+
transform.mongoObjectToParseObject('TestObject', input, {
516+
fields: {},
517+
});
518+
} catch (e) {
519+
expect(e).toBeDefined();
520+
}
521+
done();
482522
});
483523

484524
describe('transformUpdate', () => {

spec/ParseObject.spec.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,16 @@ describe('Parse.Object testing', () => {
276276
done();
277277
});
278278

279+
it('can set authData when not user class', async () => {
280+
const obj = new Parse.Object('TestObject');
281+
obj.set('authData', 'random');
282+
await obj.save();
283+
expect(obj.get('authData')).toBe('random');
284+
const query = new Parse.Query('TestObject');
285+
const object = await query.get(obj.id, { useMasterKey: true });
286+
expect(object.get('authData')).toBe('random');
287+
});
288+
279289
it('invalid class name', function(done) {
280290
const item = new Parse.Object('Foo^bar');
281291
item.save().then(

spec/ParseUser.spec.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,32 @@ describe('Parse.User testing', () => {
12461246
done();
12471247
});
12481248

1249+
it('can not set authdata to null', async () => {
1250+
try {
1251+
const provider = getMockFacebookProvider();
1252+
Parse.User._registerAuthenticationProvider(provider);
1253+
const user = await Parse.User._logInWith('facebook');
1254+
user.set('authData', null);
1255+
await user.save();
1256+
fail();
1257+
} catch (e) {
1258+
expect(e.message).toBe('This authentication method is unsupported.');
1259+
}
1260+
});
1261+
1262+
it('ignore setting authdata to undefined', async () => {
1263+
const provider = getMockFacebookProvider();
1264+
Parse.User._registerAuthenticationProvider(provider);
1265+
const user = await Parse.User._logInWith('facebook');
1266+
user.set('authData', undefined);
1267+
await user.save();
1268+
let authData = user.get('authData');
1269+
expect(authData).toBe(undefined);
1270+
await user.fetch();
1271+
authData = user.get('authData');
1272+
expect(authData.facebook.id).toBeDefined();
1273+
});
1274+
12491275
it('user authData should be available in cloudcode (#2342)', async done => {
12501276
Parse.Cloud.define('checkLogin', req => {
12511277
expect(req.user).not.toBeUndefined();
@@ -3924,4 +3950,29 @@ describe('Security Advisory GHSA-8w3j-g983-8jh5', function() {
39243950
done();
39253951
}
39263952
);
3953+
it_only_db('mongo')('should ignore authData field', async () => {
3954+
// Add User to Database with authData
3955+
const database = Config.get(Parse.applicationId).database;
3956+
const collection = await database.adapter._adaptiveCollection('_User');
3957+
await collection.insertOne({
3958+
_id: '1234ABCDEF',
3959+
name: '<some_name>',
3960+
email: '<some_email>',
3961+
username: '<some_username>',
3962+
_hashed_password: '<some_password>',
3963+
_auth_data_custom: {
3964+
id: 'linkedID',
3965+
},
3966+
sessionToken: '<some_session_token>',
3967+
authData: null, // should ignore
3968+
});
3969+
const provider = {
3970+
getAuthType: () => 'custom',
3971+
restoreAuthentication: () => true,
3972+
};
3973+
Parse.User._registerAuthenticationProvider(provider);
3974+
const query = new Parse.Query(Parse.User);
3975+
const user = await query.get('1234ABCDEF', { useMasterKey: true });
3976+
expect(user.get('authData')).toEqual({ custom: { id: 'linkedID' } });
3977+
});
39273978
});

src/Adapters/Storage/Mongo/MongoTransform.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1403,10 +1403,19 @@ const mongoObjectToParseObject = (className, mongoObject, schema) => {
14031403
case 'times_used':
14041404
restObject['timesUsed'] = mongoObject[key];
14051405
break;
1406+
case 'authData':
1407+
if (className === '_User') {
1408+
log.warn(
1409+
'ignoring authData in _User as this key is reserved to be synthesized of `_auth_data_*` keys'
1410+
);
1411+
} else {
1412+
restObject['authData'] = mongoObject[key];
1413+
}
1414+
break;
14061415
default:
14071416
// Check other auth data keys
14081417
var authDataMatch = key.match(/^_auth_data_([a-zA-Z0-9_]+)$/);
1409-
if (authDataMatch) {
1418+
if (authDataMatch && className === '_User') {
14101419
var provider = authDataMatch[1];
14111420
restObject['authData'] = restObject['authData'] || {};
14121421
restObject['authData'][provider] = mongoObject[key];

src/RestWrite.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,21 @@ RestWrite.prototype.validateAuthData = function() {
417417
}
418418
}
419419

420-
if (!this.data.authData || !Object.keys(this.data.authData).length) {
420+
if (
421+
(this.data.authData && !Object.keys(this.data.authData).length) ||
422+
!Object.prototype.hasOwnProperty.call(this.data, 'authData')
423+
) {
424+
// Handle saving authData to {} or if authData doesn't exist
421425
return;
426+
} else if (
427+
Object.prototype.hasOwnProperty.call(this.data, 'authData') &&
428+
!this.data.authData
429+
) {
430+
// Handle saving authData to null
431+
throw new Parse.Error(
432+
Parse.Error.UNSUPPORTED_SERVICE,
433+
'This authentication method is unsupported.'
434+
);
422435
}
423436

424437
var authData = this.data.authData;

0 commit comments

Comments
 (0)