Skip to content

Commit ecb68df

Browse files
Merge pull request #3 from vizmo-vms/feat-allow-email-mfa-functionality
2 parents 7b353c0 + 5b848e6 commit ecb68df

File tree

5 files changed

+315
-152
lines changed

5 files changed

+315
-152
lines changed

spec/AuthenticationAdapters.spec.js

Lines changed: 143 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,9 +1143,9 @@ describe('phant auth adapter', () => {
11431143
auth: {
11441144
phantauth: {
11451145
enableInsecureAuth: true,
1146-
}
1147-
}
1148-
})
1146+
},
1147+
},
1148+
});
11491149
const authData = {
11501150
id: 'fakeid',
11511151
access_token: 'sometoken',
@@ -1218,26 +1218,29 @@ describe('facebook limited auth adapter', () => {
12181218
}
12191219
});
12201220

1221-
it_id('7bfa55ab-8fd7-4526-992e-6de3df16bf9c')(it)('should use algorithm from key header to verify id_token (facebook.com)', async () => {
1222-
const fakeClaim = {
1223-
iss: 'https://www.facebook.com',
1224-
aud: 'secret',
1225-
exp: Date.now(),
1226-
sub: 'the_user_id',
1227-
};
1228-
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1229-
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1230-
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
1231-
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1232-
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1221+
it_id('7bfa55ab-8fd7-4526-992e-6de3df16bf9c')(it)(
1222+
'should use algorithm from key header to verify id_token (facebook.com)',
1223+
async () => {
1224+
const fakeClaim = {
1225+
iss: 'https://www.facebook.com',
1226+
aud: 'secret',
1227+
exp: Date.now(),
1228+
sub: 'the_user_id',
1229+
};
1230+
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1231+
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1232+
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
1233+
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1234+
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
12331235

1234-
const result = await facebook.validateAuthData(
1235-
{ id: 'the_user_id', token: 'the_token' },
1236-
{ clientId: 'secret' }
1237-
);
1238-
expect(result).toEqual(fakeClaim);
1239-
expect(jwt.verify.calls.first().args[2].algorithms).toEqual(fakeDecodedToken.header.alg);
1240-
});
1236+
const result = await facebook.validateAuthData(
1237+
{ id: 'the_user_id', token: 'the_token' },
1238+
{ clientId: 'secret' }
1239+
);
1240+
expect(result).toEqual(fakeClaim);
1241+
expect(jwt.verify.calls.first().args[2].algorithms).toEqual(fakeDecodedToken.header.alg);
1242+
}
1243+
);
12411244

12421245
it('should not verify invalid id_token', async () => {
12431246
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
@@ -1268,89 +1271,101 @@ describe('facebook limited auth adapter', () => {
12681271
}
12691272
});
12701273

1271-
it_id('4bcb1a1a-11f8-4e12-a3f6-73f7e25e355a')(it)('using client id as string) should verify id_token (facebook.com)', async () => {
1272-
const fakeClaim = {
1273-
iss: 'https://www.facebook.com',
1274-
aud: 'secret',
1275-
exp: Date.now(),
1276-
sub: 'the_user_id',
1277-
};
1278-
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1279-
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1280-
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1281-
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1282-
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1283-
1284-
const result = await facebook.validateAuthData(
1285-
{ id: 'the_user_id', token: 'the_token' },
1286-
{ clientId: 'secret' }
1287-
);
1288-
expect(result).toEqual(fakeClaim);
1289-
});
1290-
1291-
it_id('c521a272-2ac2-4d8b-b5ed-ea250336d8b1')(it)('(using client id as array) should verify id_token (facebook.com)', async () => {
1292-
const fakeClaim = {
1293-
iss: 'https://www.facebook.com',
1294-
aud: 'secret',
1295-
exp: Date.now(),
1296-
sub: 'the_user_id',
1297-
};
1298-
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1299-
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1300-
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1301-
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1302-
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1303-
1304-
const result = await facebook.validateAuthData(
1305-
{ id: 'the_user_id', token: 'the_token' },
1306-
{ clientId: ['secret'] }
1307-
);
1308-
expect(result).toEqual(fakeClaim);
1309-
});
1310-
1311-
it_id('e3f16404-18e9-4a87-a555-4710cfbdac67')(it)('(using client id as array with multiple items) should verify id_token (facebook.com)', async () => {
1312-
const fakeClaim = {
1313-
iss: 'https://www.facebook.com',
1314-
aud: 'secret',
1315-
exp: Date.now(),
1316-
sub: 'the_user_id',
1317-
};
1318-
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1319-
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1320-
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1321-
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1322-
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1323-
1324-
const result = await facebook.validateAuthData(
1325-
{ id: 'the_user_id', token: 'the_token' },
1326-
{ clientId: ['secret', 'secret 123'] }
1327-
);
1328-
expect(result).toEqual(fakeClaim);
1329-
});
1330-
1331-
it_id('549c33a1-3a6b-4732-8cf6-8f010ad4569c')(it)('(using client id as string) should throw error with with invalid jwt issuer (facebook.com)', async () => {
1332-
const fakeClaim = {
1333-
iss: 'https://not.facebook.com',
1334-
sub: 'the_user_id',
1335-
};
1336-
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1337-
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1338-
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1339-
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1340-
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1341-
1342-
try {
1343-
await facebook.validateAuthData(
1274+
it_id('4bcb1a1a-11f8-4e12-a3f6-73f7e25e355a')(it)(
1275+
'using client id as string) should verify id_token (facebook.com)',
1276+
async () => {
1277+
const fakeClaim = {
1278+
iss: 'https://www.facebook.com',
1279+
aud: 'secret',
1280+
exp: Date.now(),
1281+
sub: 'the_user_id',
1282+
};
1283+
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1284+
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1285+
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1286+
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1287+
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1288+
1289+
const result = await facebook.validateAuthData(
13441290
{ id: 'the_user_id', token: 'the_token' },
13451291
{ clientId: 'secret' }
13461292
);
1347-
fail();
1348-
} catch (e) {
1349-
expect(e.message).toBe(
1350-
'id token not issued by correct OpenID provider - expected: https://www.facebook.com | from: https://not.facebook.com'
1293+
expect(result).toEqual(fakeClaim);
1294+
}
1295+
);
1296+
1297+
it_id('c521a272-2ac2-4d8b-b5ed-ea250336d8b1')(it)(
1298+
'(using client id as array) should verify id_token (facebook.com)',
1299+
async () => {
1300+
const fakeClaim = {
1301+
iss: 'https://www.facebook.com',
1302+
aud: 'secret',
1303+
exp: Date.now(),
1304+
sub: 'the_user_id',
1305+
};
1306+
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1307+
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1308+
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1309+
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1310+
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1311+
1312+
const result = await facebook.validateAuthData(
1313+
{ id: 'the_user_id', token: 'the_token' },
1314+
{ clientId: ['secret'] }
13511315
);
1316+
expect(result).toEqual(fakeClaim);
13521317
}
1353-
});
1318+
);
1319+
1320+
it_id('e3f16404-18e9-4a87-a555-4710cfbdac67')(it)(
1321+
'(using client id as array with multiple items) should verify id_token (facebook.com)',
1322+
async () => {
1323+
const fakeClaim = {
1324+
iss: 'https://www.facebook.com',
1325+
aud: 'secret',
1326+
exp: Date.now(),
1327+
sub: 'the_user_id',
1328+
};
1329+
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1330+
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1331+
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1332+
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1333+
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1334+
1335+
const result = await facebook.validateAuthData(
1336+
{ id: 'the_user_id', token: 'the_token' },
1337+
{ clientId: ['secret', 'secret 123'] }
1338+
);
1339+
expect(result).toEqual(fakeClaim);
1340+
}
1341+
);
1342+
1343+
it_id('549c33a1-3a6b-4732-8cf6-8f010ad4569c')(it)(
1344+
'(using client id as string) should throw error with with invalid jwt issuer (facebook.com)',
1345+
async () => {
1346+
const fakeClaim = {
1347+
iss: 'https://not.facebook.com',
1348+
sub: 'the_user_id',
1349+
};
1350+
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1351+
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1352+
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1353+
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1354+
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1355+
1356+
try {
1357+
await facebook.validateAuthData(
1358+
{ id: 'the_user_id', token: 'the_token' },
1359+
{ clientId: 'secret' }
1360+
);
1361+
fail();
1362+
} catch (e) {
1363+
expect(e.message).toBe(
1364+
'id token not issued by correct OpenID provider - expected: https://www.facebook.com | from: https://not.facebook.com'
1365+
);
1366+
}
1367+
}
1368+
);
13541369

13551370
// TODO: figure out a way to generate our own facebook signed tokens, perhaps with a parse facebook account
13561371
// and a private key
@@ -1459,28 +1474,31 @@ describe('facebook limited auth adapter', () => {
14591474
}
14601475
});
14611476

1462-
it_id('c194d902-e697-46c9-a303-82c2d914473c')(it)('should throw error with with invalid user id (facebook.com)', async () => {
1463-
const fakeClaim = {
1464-
iss: 'https://www.facebook.com',
1465-
aud: 'invalid_client_id',
1466-
sub: 'a_different_user_id',
1467-
};
1468-
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1469-
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1470-
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1471-
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1472-
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1473-
1474-
try {
1475-
await facebook.validateAuthData(
1476-
{ id: 'the_user_id', token: 'the_token' },
1477-
{ clientId: 'secret' }
1478-
);
1479-
fail();
1480-
} catch (e) {
1481-
expect(e.message).toBe('auth data is invalid for this user.');
1477+
it_id('c194d902-e697-46c9-a303-82c2d914473c')(it)(
1478+
'should throw error with with invalid user id (facebook.com)',
1479+
async () => {
1480+
const fakeClaim = {
1481+
iss: 'https://www.facebook.com',
1482+
aud: 'invalid_client_id',
1483+
sub: 'a_different_user_id',
1484+
};
1485+
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
1486+
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
1487+
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
1488+
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
1489+
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
1490+
1491+
try {
1492+
await facebook.validateAuthData(
1493+
{ id: 'the_user_id', token: 'the_token' },
1494+
{ clientId: 'secret' }
1495+
);
1496+
fail();
1497+
} catch (e) {
1498+
expect(e.message).toBe('auth data is invalid for this user.');
1499+
}
14821500
}
1483-
});
1501+
);
14841502
});
14851503

14861504
describe('OTP TOTP auth adatper', () => {
@@ -1764,7 +1782,10 @@ describe('OTP SMS auth adatper', () => {
17641782
spy.calls.reset();
17651783

17661784
await expectAsync(Parse.User.logIn('username', 'password')).toBeRejectedWith(
1767-
new Parse.Error(Parse.Error.OTHER_CAUSE, 'Missing additional authData mfa')
1785+
new Parse.Error(
1786+
Parse.Error.OTHER_CAUSE,
1787+
'Missing additional authData mfa Send request for additional auth data'
1788+
)
17681789
);
17691790
const res = await request({
17701791
headers,

spec/AuthenticationAdaptersV2.spec.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,11 @@ describe('Auth Adapter features', () => {
361361
break;
362362
}
363363
}
364-
expect(afterSpy).toHaveBeenCalledWith(
365-
{ id: 'modernAdapter3Data' },
366-
undefined,
367-
{ ip: '127.0.0.1', user, master: false },
368-
);
364+
expect(afterSpy).toHaveBeenCalledWith({ id: 'modernAdapter3Data' }, undefined, {
365+
ip: '127.0.0.1',
366+
user,
367+
master: false,
368+
});
369369
expect(spy).toHaveBeenCalled();
370370
});
371371

@@ -488,7 +488,7 @@ describe('Auth Adapter features', () => {
488488

489489
await user.save({
490490
authData: {
491-
baseAdapter: { id: 'baseAdapter', token: "sometoken1" },
491+
baseAdapter: { id: 'baseAdapter', token: 'sometoken1' },
492492
},
493493
});
494494

@@ -497,7 +497,7 @@ describe('Auth Adapter features', () => {
497497
const user2 = new Parse.User();
498498
await user2.save({
499499
authData: {
500-
baseAdapter: { id: 'baseAdapter', token: "sometoken2" },
500+
baseAdapter: { id: 'baseAdapter', token: 'sometoken2' },
501501
},
502502
});
503503

@@ -525,7 +525,9 @@ describe('Auth Adapter features', () => {
525525
baseAdapter: { id: 'baseAdapter' },
526526
},
527527
})
528-
).toBeRejectedWithError('Missing additional authData additionalAdapter');
528+
).toBeRejectedWithError(
529+
'Missing additional authData additionalAdapter Send request for additional auth data'
530+
);
529531
expect(user2.getSessionToken()).toBeUndefined();
530532

531533
await user2.save({

0 commit comments

Comments
 (0)