Skip to content
This repository has been archived by the owner. It is now read-only.

feat: signin unblock #4154

Merged
Merged

Conversation

@shane-tomlinson
Copy link
Member

@shane-tomlinson shane-tomlinson commented Sep 15, 2016

fixes #4036

@shane-tomlinson shane-tomlinson added this to the FxA-106: email captcha milestone Sep 15, 2016
@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch 6 times, most recently from 084dd4d to 1c454ca Sep 30, 2016
@shane-tomlinson
Copy link
Member Author

@shane-tomlinson shane-tomlinson commented Sep 30, 2016

Ugh, sorry for the gigantic diff. @vbudhram, @seanmonstar, @vladikoff - r?

Going to try to put onto a dev box with @seanmonstar's PRs too.

@shane-tomlinson
Copy link
Member Author

@shane-tomlinson shane-tomlinson commented Sep 30, 2016

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.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

Add email as a @param

@@ -183,7 +183,7 @@ define([
},

'data-flow-begin attribute is set': function () {
this.remote
return this.remote

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

Revert this change - it'll be fixed by fixing #4219

.then(testElementExists('#fxa-settings-header'));
},

'report signin link uid broken': function () {

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

This test fails locally.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

Fixed it!

*
* @returns {promise} resolves with response when complete.
*/
sendUnblockEmail: withClient((client, email) => {

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

nit: missing doc, unlike the function below

/**
* Reject an unblock code.
*
* @param {string} uid - user id

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

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

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

login authorization code -> login unblock code ?

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

I would call this code -> unblockCode I think

},

/**
* Reject a login authorization code.

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

Reject a login authorization code. -> Reject a signin unblock code. ?

/**
* Reject a login authorization code.
*
* @param {string} code

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

unblockCode ?

})
.fail((err) => {
function isUnblockableError(err) {
return err.verificationMethod === 'email-captcha';

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

move 'email-captcha' into a const into file above ?

This comment has been minimized.

return err.verificationMethod === 'email-captcha';
}

if (isUnblockableError(err)) {

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

might need metrics events for the unblock err dance here

This comment has been minimized.

@shane-tomlinson

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?

},

context () {
const verificationInfo = this._verificationInfo;

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

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) {

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

nit: maybe a doc above about this view

.fail((err) => this.onSignInError(account, password, err));
},

onSignInError (account, password, err) {

This comment has been minimized.

@vladikoff

vladikoff Sep 30, 2016
Contributor

hm surprised to see this error handler in sign_in_unblock.

This comment has been minimized.

@shane-tomlinson

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.

* 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

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

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>

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

for sure we should add it.

</section>

<div class="links">
<a href="https://support.mozilla.org">{{#t}}Why is this happening?{{/t}}</a>

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

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>

This comment has been minimized.

@shane-tomlinson

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.

})
.fail((err) => {
function isUnblockableError(err) {
return err.verificationMethod === 'email-captcha';

This comment has been minimized.

return err.verificationMethod === 'email-captcha';
}

if (isUnblockableError(err)) {

This comment has been minimized.

@shane-tomlinson

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?

* 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) {

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

Add a top level doc.

.fail((err) => this.onSignInError(account, password, err));
},

onSignInError (account, password, err) {

This comment has been minimized.

@shane-tomlinson

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.

onSignInError (account, password, err) {
if (AuthErrors.is(err, 'INCORRECT_PASSWORD')) {
// The user must go enter the correct password this time.
this.navigate('signin', {

This comment has been minimized.

@shane-tomlinson

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.

.then(testElementExists('#fxa-settings-header'));
},

'report signin link uid broken': function () {

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Sep 30, 2016
Author Member

Fixed it!

@vladikoff
Copy link
Contributor

@vladikoff vladikoff commented Sep 30, 2016

got a bit stuck here
image

@vladikoff
Copy link
Contributor

@vladikoff vladikoff commented Sep 30, 2016

There is an issue with

Correct Code ->> Incorrect Password ->> Press back button ->> arrive to "signin_unblock" with no query params

and I think that threw "invalid code". I'm guessing we would need to handle the "back" case somehow.

@shane-tomlinson
Copy link
Member Author

@shane-tomlinson shane-tomlinson commented Oct 3, 2016

got a bit stuck here

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:

I was able to get into a non-unblockable situation by doing the following:

  • Attempting signin to a bunch of non-existing accounts, then
  • Attempting signin with the wrong password on my real account

The result was a 429 while calling /send_unblock_code, and UX as shown
in the attached screenshot.

My mental model of what happened is that my IP was rate-limited due to
the failed logins on different accounts, and since rate-limited IPs are
not allowed to do anything, this blocked the sending of the
authorization code email.

Sean, you might remember this failure mode from our time digging into
that weird "Don't block email-sending on IP address alone" comment in
the customs-server:

mozilla/fxa-customs-server@9a4eaf5

Perhaps the right thing in the short term, is to improve the UX of this
failure case, by only transitioning to the "we sent you an authorization
code" screen after we've successfully sent the code.

@shane-tomlinson
Copy link
Member Author

@shane-tomlinson shane-tomlinson commented Oct 3, 2016

There is an issue with

Correct Code ->> Incorrect Password ->> Press back button ->> arrive to "signin_unblock" with no query params

and I think that threw "invalid code". I'm guessing we would need to handle the "back" case somehow.

Good find!

Copy link
Contributor

@vbudhram vbudhram left a comment

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);

This comment has been minimized.

@vbudhram

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

},

/**
* Report/reject the unblockCode for the given account

This comment has been minimized.

@vbudhram

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 comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 10, 2016
Author Member

Yup.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 12, 2016
Author Member

Comment updated.


if (isRequired && ! value.length) {
throw AuthErrors.toError('UNBLOCK_CODE_REQUIRED');
} else if (value.length !== Constants.UNBLOCK_CODE_LENGTH) {

This comment has been minimized.

@vbudhram

vbudhram Oct 3, 2016
Contributor

Can probably be replace with regex as well.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 4, 2016
Author Member

Can probably be replace with regex as well.

I replaced this check with Validate.isUnblockCodeValid

@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch from 2d6740b to 9cead46 Oct 3, 2016
@shane-tomlinson
Copy link
Member Author

@shane-tomlinson shane-tomlinson commented Oct 4, 2016

Problems/follow on work @ryanfeeley and I found today when testing:

  • Incorrect password from force_auth does not allow the user to enter the correct password, upon return to /force_auth, the screen is blank except for an error that says "Incorrect password"
  • Incorrect password from signup sends the user back to the signup page from signin_unblock, it should instead send the user to the signin page.
  • Check how the screen appears from the firstrun page.
  • Signin with an unverified account - the user must first enter the unblock code, THEN they see the "verify your account" screen.
  • Doesn't work for Sync (user isn't forced through flow)
@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch from fae3ad9 to 77125d5 Oct 6, 2016
@@ -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.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 10, 2016
Author Member

This comment should be expanded upon.

@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch 4 times, most recently from 4d44c4a to 27f724b Oct 10, 2016
@shane-tomlinson
Copy link
Member Author

@shane-tomlinson shane-tomlinson commented Oct 12, 2016

Signin with an unverified account - the user must first enter the unblock code, THEN they see the "verify your account" screen.

We have decided to punt on this for now.

Copy link
Contributor

@philbooth philbooth left a comment

LGTM 👍

let alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';

for (let i = 0; i < length; ++i) {
let indexToUse = Math.floor(Math.random() * base);

This comment has been minimized.

@philbooth

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.

This comment has been minimized.

@shane-tomlinson

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.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 12, 2016
Author Member

on server side code though, we should probably absolutely worry about it.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 12, 2016
Author Member

probably absolutely. Yes. English, not my strongest subject.

This comment has been minimized.

@seanmonstar

seanmonstar Oct 12, 2016
Member

Why move the let outside the for? It seems like exactly what is designed for: block level scoping.

This comment has been minimized.

@shane-tomlinson

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.

},

/**
* Report/reject the unblockCode for the given account

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 12, 2016
Author Member

Comment updated.

</section>

<div class="links">
<a href="https://support.mozilla.org">{{#t}}Why is this happening?{{/t}}</a>

This comment has been minimized.

@shane-tomlinson

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.

const lastPage = this.model.get('lastPage');

if (lastPage === 'force_auth') {
return 'force_auth';

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 12, 2016
Author Member

Normalize these to handle the oauth case - this can be done using this.broker.transformLink.


describe('rejectAccountUnblockCode', () => {
let account;
let UNBLOCK_CODE = '12345678';

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 12, 2016
Author Member

This could be a const

@rfk
Copy link
Member

@rfk rfk commented Oct 12, 2016

We have decided to punt on this for now.

@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

@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch from 7b39cac to b2969d2 Oct 12, 2016
.then(testElementTextInclude('.verification-email-message', email))
.then(type('#unblock_code', 'i'))
.then(click('button[type=submit]'));
// TODO - check for an error here.

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 13, 2016
Author Member

Fix the TODO!

@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch 2 times, most recently from baeeb75 to f3eee32 Oct 14, 2016
@shane-tomlinson shane-tomlinson changed the title WIP Fxa106 signin unblock authorization captcha own screen feat: signin unblock Oct 14, 2016
@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch from f3eee32 to 300ae17 Oct 14, 2016
@@ -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);

This comment has been minimized.

@shane-tomlinson

shane-tomlinson Oct 14, 2016
Author Member

revert this change.

@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch from 300ae17 to feb97bf Oct 14, 2016
@shane-tomlinson shane-tomlinson force-pushed the fxa106-signin-authorization-captcha-own-screen branch from feb97bf to cf2d06f Oct 14, 2016
@shane-tomlinson shane-tomlinson merged commit 18850e1 into master Oct 17, 2016
4 checks passed
4 checks passed
ci/circleci Your tests passed on CircleCI!
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details
coverage/coveralls Coverage increased (+0.008%) to 98.772%
Details
@shane-tomlinson shane-tomlinson deleted the fxa106-signin-authorization-captcha-own-screen branch Oct 17, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

6 participants