Skip to content

Commit eec0a26

Browse files
committed
fix: customise missing additional authData and hash email while saving, and fix for user saving
1 parent 1fe3a64 commit eec0a26

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

src/Adapters/Auth/mfa.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
*/
7979

8080
import { TOTP, Secret } from 'otpauth';
81+
import crypto from 'crypto';
8182
import { randomString } from '../../cryptoUtils';
8283
import AuthAdapter from './AuthAdapter';
8384
class MFAAdapter extends AuthAdapter {
@@ -149,17 +150,32 @@ class MFAAdapter extends AuthAdapter {
149150
if (this.email && email) {
150151
if (token === 'request') {
151152
const { token: sendToken, expiry } = await this.sendEmail(email);
152-
auth.mfa.token = sendToken;
153-
auth.mfa.expiry = expiry;
154-
req.object.set('authData', auth);
155-
await req.object.save(null, { useMasterKey: true });
156-
throw 'Please enter the token';
153+
const auth = req.original.get('authData') || {};
154+
auth.mfa = {
155+
token: sendToken,
156+
email: email,
157+
expiry: expiry
158+
};
159+
160+
// Use direct database access to avoid validation
161+
const query = new Parse.Query(Parse.User);
162+
const user = await query.get(req.object.id, { useMasterKey: true });
163+
user.set('authData', auth);
164+
165+
// Skip validation and hooks
166+
await user.save(null, {
167+
useMasterKey: true,
168+
context: { skipValidation: true },
169+
validateSave: false
170+
});
171+
172+
throw new Parse.Error(209,'Please enter the token');
157173
}
158174
if (!saved || token !== saved) {
159175
throw 'Invalid MFA token 1';
160176
}
161177
if (new Date() > expiry) {
162-
throw 'Invalid MFA token 2';
178+
throw 'Expired MFA token';
163179
}
164180
delete auth.mfa.token;
165181
delete auth.mfa.expiry;
@@ -283,10 +299,12 @@ class MFAAdapter extends AuthAdapter {
283299

284300
async setupEmailOTP(email) {
285301
const { token, expiry } = await this.sendEmail(email);
302+
const emailHash = this.md5Hash(email);
286303
return {
287304
save: {
288305
pending: {
289-
[email]: {
306+
// encode the email md5 has
307+
[emailHash]: {
290308
token,
291309
expiry,
292310
},
@@ -344,17 +362,18 @@ class MFAAdapter extends AuthAdapter {
344362

345363
async confirmEmailOTP(inputData, authData) {
346364
const { email, token } = inputData;
347-
if (!authData.pending?.[email]) {
365+
const emailHash = this.md5Hash(email);
366+
if (!authData.pending?.[emailHash]) {
348367
throw 'This email is not pending';
349368
}
350-
const pendingData = authData.pending[email];
369+
const pendingData = authData.pending[emailHash];
351370
if (token !== pendingData.token) {
352371
throw 'Invalid MFA token';
353372
}
354373
if (new Date() > pendingData.expiry) {
355374
throw 'Invalid MFA token';
356375
}
357-
delete authData.pending[email];
376+
delete authData.pending[emailHash];
358377
authData.email = email;
359378
return {
360379
save: authData,
@@ -384,5 +403,8 @@ class MFAAdapter extends AuthAdapter {
384403
save: { secret, recovery },
385404
};
386405
}
406+
md5Hash(str) {
407+
return crypto.createHash('md5').update(str).digest('hex');
408+
}
387409
}
388410
export default new MFAAdapter();

src/Auth.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,10 +505,17 @@ const checkIfUserHasProvidedConfiguredProvidersForLogin = (
505505
return;
506506
}
507507

508-
throw new Parse.Error(
509-
Parse.Error.OTHER_CAUSE,
510-
`Missing additional authData ${additionProvidersNotFound.join(',')}`
511-
);
508+
let errorMsg = `Missing additional authData ${additionProvidersNotFound.join(',')}`
509+
if(additionProvidersNotFound.length>0){
510+
const mfaData = userAuthData.mfa || {};
511+
const needsToken = !mfaData.secret && (mfaData.email || mfaData.mobile);
512+
const additionalInfo = needsToken
513+
? " (include 'request' as token to receive a verification code)"
514+
: "";
515+
516+
errorMsg += additionalInfo;
517+
}
518+
throw new Parse.Error(Parse.Error.OTHER_CAUSE, errorMsg);
512519
};
513520

514521
// Validate each authData step-by-step and return the provider responses

0 commit comments

Comments
 (0)