Skip to content

Commit 877ef78

Browse files
aontasflovilmart
authored andcommitted
Improve email verification (#3681)
* Removed hidden keys from users/me. * Ensured that general users cannot update email verified flag. * Updated tests to reflect email verification changes.
1 parent 81a55e6 commit 877ef78

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

spec/ParseUser.spec.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,4 +2818,121 @@ describe('Parse.User testing', () => {
28182818
done();
28192819
});
28202820
});
2821+
2822+
it('should not allow updates to emailVerified', done => {
2823+
var emailAdapter = {
2824+
sendVerificationEmail: () => {},
2825+
sendPasswordResetEmail: () => Promise.resolve(),
2826+
sendMail: () => Promise.resolve()
2827+
}
2828+
2829+
const user = new Parse.User();
2830+
user.set({
2831+
username: 'hello',
2832+
password: 'world',
2833+
2834+
})
2835+
2836+
reconfigureServer({
2837+
appName: 'unused',
2838+
verifyUserEmails: true,
2839+
emailAdapter: emailAdapter,
2840+
publicServerURL: "http://localhost:8378/1"
2841+
}).then(() => {
2842+
return user.signUp();
2843+
}).then(() => {
2844+
return Parse.User.current().set('emailVerified', true).save();
2845+
}).then(() => {
2846+
fail("Should not be able to update emailVerified");
2847+
done();
2848+
}).catch((err) => {
2849+
expect(err.message).toBe("Clients aren't allowed to manually update email verification.");
2850+
done();
2851+
});
2852+
});
2853+
2854+
it('should not retrieve hidden fields', done => {
2855+
2856+
var emailAdapter = {
2857+
sendVerificationEmail: () => {},
2858+
sendPasswordResetEmail: () => Promise.resolve(),
2859+
sendMail: () => Promise.resolve()
2860+
}
2861+
2862+
const user = new Parse.User();
2863+
user.set({
2864+
username: 'hello',
2865+
password: 'world',
2866+
2867+
})
2868+
2869+
reconfigureServer({
2870+
appName: 'unused',
2871+
verifyUserEmails: true,
2872+
emailAdapter: emailAdapter,
2873+
publicServerURL: "http://localhost:8378/1"
2874+
}).then(() => {
2875+
return user.signUp();
2876+
}).then(() => rp({
2877+
method: 'GET',
2878+
url: 'http://localhost:8378/1/users/me',
2879+
json: true,
2880+
headers: {
2881+
'X-Parse-Application-Id': Parse.applicationId,
2882+
'X-Parse-Session-Token': Parse.User.current().getSessionToken(),
2883+
'X-Parse-REST-API-Key': 'rest'
2884+
},
2885+
})).then((res) => {
2886+
expect(res.emailVerified).toBe(false);
2887+
expect(res._email_verify_token).toBeUndefined();
2888+
done()
2889+
}).then(() => rp({
2890+
method: 'GET',
2891+
url: 'http://localhost:8378/1/users/' + Parse.User.current().id,
2892+
json: true,
2893+
headers: {
2894+
'X-Parse-Application-Id': Parse.applicationId,
2895+
'X-Parse-REST-API-Key': 'rest'
2896+
},
2897+
})).then((res) => {
2898+
expect(res.emailVerified).toBe(false);
2899+
expect(res._email_verify_token).toBeUndefined();
2900+
done()
2901+
}).catch((err) => {
2902+
fail(JSON.stringify(err));
2903+
done();
2904+
});
2905+
});
2906+
2907+
it('should not allow updates to hidden fields', done => {
2908+
var emailAdapter = {
2909+
sendVerificationEmail: () => {},
2910+
sendPasswordResetEmail: () => Promise.resolve(),
2911+
sendMail: () => Promise.resolve()
2912+
}
2913+
2914+
const user = new Parse.User();
2915+
user.set({
2916+
username: 'hello',
2917+
password: 'world',
2918+
2919+
})
2920+
2921+
reconfigureServer({
2922+
appName: 'unused',
2923+
verifyUserEmails: true,
2924+
emailAdapter: emailAdapter,
2925+
publicServerURL: "http://localhost:8378/1"
2926+
}).then(() => {
2927+
return user.signUp();
2928+
}).then(() => {
2929+
return Parse.User.current().set('_email_verify_token', 'bad').save();
2930+
}).then(() => {
2931+
fail("Should not be able to update email verification token");
2932+
done();
2933+
}).catch((err) => {
2934+
expect(err).toBeDefined();
2935+
done();
2936+
});
2937+
});
28212938
});

src/RestWrite.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ RestWrite.prototype.transformUser = function() {
349349
return promise;
350350
}
351351

352+
if (!this.auth.isMaster && "emailVerified" in this.data) {
353+
const error = `Clients aren't allowed to manually update email verification.`
354+
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
355+
}
356+
352357
if (this.query) {
353358
// If we're updating a _User object, we need to clear out the cache for that user. Find all their
354359
// session tokens, and remove them from the cache.

src/Routers/UsersRouter.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ export class UsersRouter extends ClassesRouter {
5757
const user = response.results[0].user;
5858
// Send token back on the login, because SDKs expect that.
5959
user.sessionToken = sessionToken;
60+
61+
// Remove hidden properties.
62+
for (var key in user) {
63+
if (user.hasOwnProperty(key)) {
64+
// Regexp comes from Parse.Object.prototype.validate
65+
if (key !== "__type" && !(/^[A-Za-z][0-9A-Za-z_]*$/).test(key)) {
66+
delete user[key];
67+
}
68+
}
69+
}
70+
6071
return { response: user };
6172
}
6273
});

0 commit comments

Comments
 (0)