feat: signin unblock #4154
feat: signin unblock #4154
Conversation
084dd4d
to
1c454ca
|
Ugh, sorry for the gigantic diff. @vbudhram, @seanmonstar, @vladikoff - r? Going to try to put onto a dev box with @seanmonstar's PRs too. |
|
And now some functional tests fail. Still, let's start review to get feedback on code. |
| /** | ||
| * Send an unblock email. | ||
| * | ||
| * @returns {promise} resolves with response when complete. |
shane-tomlinson
Sep 30, 2016
Author
Member
Add email as a @param
Add email as a @param
| @@ -183,7 +183,7 @@ define([ | |||
| }, | |||
|
|
|||
| 'data-flow-begin attribute is set': function () { | |||
| this.remote | |||
| return this.remote | |||
| .then(testElementExists('#fxa-settings-header')); | ||
| }, | ||
|
|
||
| 'report signin link uid broken': function () { |
shane-tomlinson
Sep 30, 2016
Author
Member
This test fails locally.
This test fails locally.
shane-tomlinson
Sep 30, 2016
Author
Member
Fixed it!
Fixed it!
| * | ||
| * @returns {promise} resolves with response when complete. | ||
| */ | ||
| sendUnblockEmail: withClient((client, email) => { |
vladikoff
Sep 30, 2016
•
Contributor
nit: missing doc, unlike the function below
nit: missing doc, unlike the function below
| /** | ||
| * Reject an unblock code. | ||
| * | ||
| * @param {string} uid - user id |
vladikoff
Sep 30, 2016
Contributor
nit: let's try to use {String} instead of {string}
nit: let's try to use {String} instead of {string}
| * Reject an unblock code. | ||
| * | ||
| * @param {string} uid - user id | ||
| * @param {string} code - login authorization code |
vladikoff
Sep 30, 2016
Contributor
login authorization code -> login unblock code ?
login authorization code -> login unblock code ?
vladikoff
Sep 30, 2016
Contributor
I would call this code -> unblockCode I think
I would call this code -> unblockCode I think
| }, | ||
|
|
||
| /** | ||
| * Reject a login authorization code. |
vladikoff
Sep 30, 2016
Contributor
Reject a login authorization code. -> Reject a signin unblock code. ?
Reject a login authorization code. -> Reject a signin unblock code. ?
| /** | ||
| * Reject a login authorization code. | ||
| * | ||
| * @param {string} code |
vladikoff
Sep 30, 2016
Contributor
unblockCode ?
unblockCode ?
| }) | ||
| .fail((err) => { | ||
| function isUnblockableError(err) { | ||
| return err.verificationMethod === 'email-captcha'; |
vladikoff
Sep 30, 2016
Contributor
move 'email-captcha' into a const into file above ?
move 'email-captcha' into a const into file above ?
| return err.verificationMethod === 'email-captcha'; | ||
| } | ||
|
|
||
| if (isUnblockableError(err)) { |
vladikoff
Sep 30, 2016
•
Contributor
might need metrics events for the unblock err dance here
might need metrics events for the unblock err dance here
shane-tomlinson
Sep 30, 2016
•
Author
Member
might need metrics events for the unblock err dance here
@vladikoff - is fxa.content.screen.signin_unblock sufficient?
might need metrics events for the unblock err dance here
@vladikoff - is fxa.content.screen.signin_unblock sufficient?
| }, | ||
|
|
||
| context () { | ||
| const verificationInfo = this._verificationInfo; |
vladikoff
Sep 30, 2016
Contributor
do we need this const here, we only use it once below
do we need this const here, we only use it once below
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| define(function (require, exports, module) { |
vladikoff
Sep 30, 2016
Contributor
nit: maybe a doc above about this view
nit: maybe a doc above about this view
| .fail((err) => this.onSignInError(account, password, err)); | ||
| }, | ||
|
|
||
| onSignInError (account, password, err) { |
vladikoff
Sep 30, 2016
Contributor
hm surprised to see this error handler in sign_in_unblock.
hm surprised to see this error handler in sign_in_unblock.
shane-tomlinson
Sep 30, 2016
Author
Member
We are re-signing the user in with the email/password they entered on the /signin page + the unblockCode entered here. If the user entered their password incorrectly, we'll only find out after this step, and then we have to send them back to the previous screen.
We are re-signing the user in with the email/password they entered on the /signin page + the unblockCode entered here. If the user entered their password incorrectly, we'll only find out after this step, and then we have to send them back to the previous screen.
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| /** | ||
| * A model to hold report-sign-in data. Model has a `report` function |
shane-tomlinson
Sep 30, 2016
Author
Member
Ahha, I took that out and moved it to user, good eye.
Ahha, I took that out and moved it to user, good eye.
|
|
||
| <form novalidate> | ||
| <div class="button-row"> | ||
| <button id="submit-btn" type="submit" class="disabled">{{#t}}Report activity{{/t}}</button> |
shane-tomlinson
Sep 30, 2016
Author
Member
for sure we should add it.
for sure we should add it.
| </section> | ||
|
|
||
| <div class="links"> | ||
| <a href="https://support.mozilla.org">{{#t}}Why is this happening?{{/t}}</a> |
shane-tomlinson
Sep 30, 2016
Author
Member
And we need a real link. :D
And we need a real link. :D
| <div id="main-content" class="card"> | ||
| {{#error}} | ||
| <header> | ||
| <h1 id="fxa-signin-unblock-header">{{#t}}Authorize this sign-in{{/t}}</h1> |
shane-tomlinson
Sep 30, 2016
Author
Member
Good point, I'll change this to something like "problem sending unblock email" because that's how this error condition occurs.
Good point, I'll change this to something like "problem sending unblock email" because that's how this error condition occurs.
| }) | ||
| .fail((err) => { | ||
| function isUnblockableError(err) { | ||
| return err.verificationMethod === 'email-captcha'; |
| return err.verificationMethod === 'email-captcha'; | ||
| } | ||
|
|
||
| if (isUnblockableError(err)) { |
shane-tomlinson
Sep 30, 2016
•
Author
Member
might need metrics events for the unblock err dance here
@vladikoff - is fxa.content.screen.signin_unblock sufficient?
might need metrics events for the unblock err dance here
@vladikoff - is fxa.content.screen.signin_unblock sufficient?
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| define(function (require, exports, module) { |
shane-tomlinson
Sep 30, 2016
Author
Member
Add a top level doc.
Add a top level doc.
| .fail((err) => this.onSignInError(account, password, err)); | ||
| }, | ||
|
|
||
| onSignInError (account, password, err) { |
shane-tomlinson
Sep 30, 2016
Author
Member
We are re-signing the user in with the email/password they entered on the /signin page + the unblockCode entered here. If the user entered their password incorrectly, we'll only find out after this step, and then we have to send them back to the previous screen.
We are re-signing the user in with the email/password they entered on the /signin page + the unblockCode entered here. If the user entered their password incorrectly, we'll only find out after this step, and then we have to send them back to the previous screen.
| onSignInError (account, password, err) { | ||
| if (AuthErrors.is(err, 'INCORRECT_PASSWORD')) { | ||
| // The user must go enter the correct password this time. | ||
| this.navigate('signin', { |
shane-tomlinson
Sep 30, 2016
Author
Member
Don't forget about /oauth/signin and users who arrive here from /force_auth and /oauth/force_auth.
Don't forget about /oauth/signin and users who arrive here from /force_auth and /oauth/force_auth.
| .then(testElementExists('#fxa-settings-header')); | ||
| }, | ||
|
|
||
| 'report signin link uid broken': function () { |
shane-tomlinson
Sep 30, 2016
Author
Member
Fixed it!
Fixed it!
|
There is an issue with
and I think that threw "invalid code". I'm guessing we would need to handle the "back" case somehow. |
Hard blocks still remain in place to prevent signin unblock from being used as 1) a spam vector, and 2) a free pass to guess the user's FxA password by continually going through signin unblock. Some restrictions will likely be loosened a bit, @rfk wrote this in an email thread with @seanmonstar and I:
|
Good find! |
|
Looks good so far, just a couple comments, haven't looked through tests yet. |
| * @returns {Boolean} | ||
| */ | ||
| isUnblockCodeValid (value) { | ||
| return !! (value && value.length === Constants.UNBLOCK_CODE_LENGTH); |
vbudhram
Oct 3, 2016
Contributor
I think it could be useful to check against the regex the auth server uses for unblock code, https://github.com/mozilla/fxa-auth-server/blob/2c0561df2aae7d166a21c05b70aaaff6efe982e8/lib/routes/validators.js#L17
I think it could be useful to check against the regex the auth server uses for unblock code, https://github.com/mozilla/fxa-auth-server/blob/2c0561df2aae7d166a21c05b70aaaff6efe982e8/lib/routes/validators.js#L17
| }, | ||
|
|
||
| /** | ||
| * Report/reject the unblockCode for the given account |
vbudhram
Oct 3, 2016
Contributor
This was a little confusing to me. I read it as either report or reject. Should it be reject and report? From looking at the auth-server endpoint, it appears to log an error, is this what is meant by report?
This was a little confusing to me. I read it as either report or reject. Should it be reject and report? From looking at the auth-server endpoint, it appears to log an error, is this what is meant by report?
shane-tomlinson
Oct 10, 2016
Author
Member
Yup.
Yup.
shane-tomlinson
Oct 12, 2016
Author
Member
Comment updated.
Comment updated.
|
|
||
| if (isRequired && ! value.length) { | ||
| throw AuthErrors.toError('UNBLOCK_CODE_REQUIRED'); | ||
| } else if (value.length !== Constants.UNBLOCK_CODE_LENGTH) { |
vbudhram
Oct 3, 2016
Contributor
Can probably be replace with regex as well.
Can probably be replace with regex as well.
shane-tomlinson
Oct 4, 2016
Author
Member
Can probably be replace with regex as well.
I replaced this check with Validate.isUnblockCodeValid
Can probably be replace with regex as well.
I replaced this check with Validate.isUnblockCodeValid
2d6740b
to
9cead46
|
Problems/follow on work @ryanfeeley and I found today when testing:
|
fae3ad9
to
77125d5
| @@ -57,6 +57,8 @@ define(function (require, exports, module) { | |||
| try { | |||
| accountData = this._getAndValidateAccountData(); | |||
| } catch (err) { | |||
| // validation errors are not handled here, rather they are | |||
| // handled XXX. | |||
shane-tomlinson
Oct 10, 2016
Author
Member
This comment should be expanded upon.
This comment should be expanded upon.
4d44c4a
to
27f724b
We have decided to punt on this for now. |
|
LGTM |
| let alphabet = '0123456789abcdefghijklmnopqrstuvwxyz'; | ||
|
|
||
| for (let i = 0; i < length; ++i) { | ||
| let indexToUse = Math.floor(Math.random() * base); |
philbooth
Oct 12, 2016
Contributor
I know this is only test code, but it sounded yesterday like we were agreeing either to move let declarations outside of loops or to use var instead.
I know this is only test code, but it sounded yesterday like we were agreeing either to move let declarations outside of loops or to use var instead.
shane-tomlinson
Oct 12, 2016
Author
Member
I'm pretty "meh" since our for loops iterate over such a small range and that was a v8 specific issue.
I'm pretty "meh" since our for loops iterate over such a small range and that was a v8 specific issue.
shane-tomlinson
Oct 12, 2016
Author
Member
on server side code though, we should probably absolutely worry about it.
on server side code though, we should probably absolutely worry about it.
shane-tomlinson
Oct 12, 2016
Author
Member
probably absolutely. Yes. English, not my strongest subject.
probably absolutely. Yes. English, not my strongest subject.
seanmonstar
Oct 12, 2016
Member
Why move the let outside the for? It seems like exactly what is designed for: block level scoping.
Why move the let outside the for? It seems like exactly what is designed for: block level scoping.
shane-tomlinson
Oct 12, 2016
Author
Member
Why move the let outside the for? It seems like exactly what is designed for: block level scoping.
@jrgm thought he heard v8 has an issue where let inside of loops is significantly slower than var.
Why move the let outside the for? It seems like exactly what is designed for: block level scoping.
@jrgm thought he heard v8 has an issue where let inside of loops is significantly slower than var.
| }, | ||
|
|
||
| /** | ||
| * Report/reject the unblockCode for the given account |
shane-tomlinson
Oct 12, 2016
Author
Member
Comment updated.
Comment updated.
| </section> | ||
|
|
||
| <div class="links"> | ||
| <a href="https://support.mozilla.org">{{#t}}Why is this happening?{{/t}}</a> |
shane-tomlinson
Oct 12, 2016
Author
Member
Remove the link until it the content is ready, or perhaps we can use an able experiment to insert the link when we have one ready.
Remove the link until it the content is ready, or perhaps we can use an able experiment to insert the link when we have one ready.
| const lastPage = this.model.get('lastPage'); | ||
|
|
||
| if (lastPage === 'force_auth') { | ||
| return 'force_auth'; |
shane-tomlinson
Oct 12, 2016
Author
Member
Normalize these to handle the oauth case - this can be done using this.broker.transformLink.
Normalize these to handle the oauth case - this can be done using this.broker.transformLink.
|
|
||
| describe('rejectAccountUnblockCode', () => { | ||
| let account; | ||
| let UNBLOCK_CODE = '12345678'; |
shane-tomlinson
Oct 12, 2016
Author
Member
This could be a const
This could be a const
@shane-tomlinson @seanmonstar please ensure we have a follow-up bug on file in the right milestone, so we don't lose track of it |
7b39cac
to
b2969d2
| .then(testElementTextInclude('.verification-email-message', email)) | ||
| .then(type('#unblock_code', 'i')) | ||
| .then(click('button[type=submit]')); | ||
| // TODO - check for an error here. |
shane-tomlinson
Oct 13, 2016
Author
Member
Fix the TODO!
Fix the TODO!
baeeb75
to
f3eee32
f3eee32
to
300ae17
| @@ -891,7 +934,7 @@ define([ | |||
| }, [command]) | |||
| .then(null, function (err) { | |||
| if (/ScriptTimeout/.test(String(err))) { | |||
| var noSuchNotificationError = new Error('NoSuchBrowserNotification'); | |||
| var noSuchNotificationError = new Error('NoSuchBrowserNotification ' + command); | |||
shane-tomlinson
Oct 14, 2016
Author
Member
revert this change.
revert this change.
300ae17
to
feb97bf
feb97bf
to
cf2d06f

fixes #4036