Skip to content

Commit

Permalink
Improve email verification (#3681)
Browse files Browse the repository at this point in the history
* Removed hidden keys from users/me.

* Ensured that general users cannot update email verified flag.

* Updated tests to reflect email verification changes.
  • Loading branch information
aontas authored and flovilmart committed May 11, 2017
1 parent 81a55e6 commit 877ef78
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
117 changes: 117 additions & 0 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2818,4 +2818,121 @@ describe('Parse.User testing', () => {
done();
});
});

it('should not allow updates to emailVerified', done => {
var emailAdapter = {
sendVerificationEmail: () => {},
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}

const user = new Parse.User();
user.set({
username: 'hello',
password: 'world',
email: "test@email.com"
})

reconfigureServer({
appName: 'unused',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
}).then(() => {
return user.signUp();
}).then(() => {
return Parse.User.current().set('emailVerified', true).save();
}).then(() => {
fail("Should not be able to update emailVerified");
done();
}).catch((err) => {
expect(err.message).toBe("Clients aren't allowed to manually update email verification.");
done();
});
});

it('should not retrieve hidden fields', done => {

var emailAdapter = {
sendVerificationEmail: () => {},
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}

const user = new Parse.User();
user.set({
username: 'hello',
password: 'world',
email: "test@email.com"
})

reconfigureServer({
appName: 'unused',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
}).then(() => {
return user.signUp();
}).then(() => rp({
method: 'GET',
url: 'http://localhost:8378/1/users/me',
json: true,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-Session-Token': Parse.User.current().getSessionToken(),
'X-Parse-REST-API-Key': 'rest'
},
})).then((res) => {
expect(res.emailVerified).toBe(false);
expect(res._email_verify_token).toBeUndefined();
done()
}).then(() => rp({
method: 'GET',
url: 'http://localhost:8378/1/users/' + Parse.User.current().id,
json: true,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest'
},
})).then((res) => {
expect(res.emailVerified).toBe(false);
expect(res._email_verify_token).toBeUndefined();
done()
}).catch((err) => {
fail(JSON.stringify(err));
done();
});
});

it('should not allow updates to hidden fields', done => {
var emailAdapter = {
sendVerificationEmail: () => {},
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve()
}

const user = new Parse.User();
user.set({
username: 'hello',
password: 'world',
email: "test@email.com"
})

reconfigureServer({
appName: 'unused',
verifyUserEmails: true,
emailAdapter: emailAdapter,
publicServerURL: "http://localhost:8378/1"
}).then(() => {
return user.signUp();
}).then(() => {
return Parse.User.current().set('_email_verify_token', 'bad').save();
}).then(() => {
fail("Should not be able to update email verification token");
done();
}).catch((err) => {
expect(err).toBeDefined();
done();
});
});
});
5 changes: 5 additions & 0 deletions src/RestWrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,11 @@ RestWrite.prototype.transformUser = function() {
return promise;
}

if (!this.auth.isMaster && "emailVerified" in this.data) {
const error = `Clients aren't allowed to manually update email verification.`
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
}

if (this.query) {
// If we're updating a _User object, we need to clear out the cache for that user. Find all their
// session tokens, and remove them from the cache.
Expand Down
11 changes: 11 additions & 0 deletions src/Routers/UsersRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ export class UsersRouter extends ClassesRouter {
const user = response.results[0].user;
// Send token back on the login, because SDKs expect that.
user.sessionToken = sessionToken;

// Remove hidden properties.
for (var key in user) {
if (user.hasOwnProperty(key)) {
// Regexp comes from Parse.Object.prototype.validate
if (key !== "__type" && !(/^[A-Za-z][0-9A-Za-z_]*$/).test(key)) {
delete user[key];
}
}
}

return { response: user };
}
});
Expand Down

0 comments on commit 877ef78

Please sign in to comment.