-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gutenboarding: Add push 2fa support to auth store #40114
Conversation
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser: App Entrypoints (~779 bytes added 📈 [gzipped])
Common code that is always downloaded and parsed every time the app is loaded, no matter which route is used. Legend What is parsed and gzip size?Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory. Generated by performance advisor bot at iscalypsofastyet.com. |
923ffe6
to
027010d
Compare
Turns out passwordless account can have a second factor! It won't impact gutenboarding though because you enter the 2nd factor after following the email link, so that's done at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't test it with the app on my phone (I got no google services 😅). I had a comment on the style of reusing variables and the login response type which I think should be a union type, and also error handling.
if ( ! response.success ) { | ||
two_step_nonce = response.data.two_step_nonce; | ||
yield wait( POLL_APP_PUSH_INTERVAL_SECONDS * 1000 ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have a timeout here, I'm not sure what length of time it should be. Is this code called as we wait for the user to acknowledge the push notification on their phone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. I don't the current login has a timeout but it really should. It does handle errors by stopping the polling, and we should too.
two_step_push_token: push_web_token, | ||
} ); | ||
|
||
if ( ! response.success ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should also be error cases which indicate that the push authentication has really failed an will never succeed. I think you should be more specific with this check and then handle any other error's seperately
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, I reckon this goes hand in hand with timing out too.
Nice work so far @p-jackson! Following the steps in the testing instructions worked well for me. I ran into an issue attempting to test when something doesn't quite work out right, like if a user doesn't have notifications switched on in the app, or accidentally clicks ignore, so we need to submit the password again. The first time I attempted this, I appeared to get stuck in a situation where there were two lots of the while loop running checking the The steps to do this were:
I attempted to recreate these steps, but encountered slightly different behaviour. I tapped "Ignore" after the first password submit, and then after the second password submit, the network requests for checking the
Inspecting the network request that generated the 400, the request payload was missing the I've run out of time for today to investigate further, but I'm wondering if in the while loop it'd be worth trying to explore how it can check the This behaviour might be a little artificial of course, because we might handle things quite differently in the consuming code. Taking a look at the existing behaviour at I'm sure you're well-aware of most of these complexities anyway, so apologies for the info dump! Happy to take a closer look again tomorrow. |
I've updated polling logic so if there's an API error the polling will stop and return the user to the password state. However if it's a network error (i.e. I decided not to add a timeout for polling. How long is long enough? Does it take a user 5min to find their phone? 10min? Instead I've made sure the |
Just tested and works as described for me.
I clicked on Ignore in my app, just to see what would happen. It's hard to guesstimate how long is appropriate. Sometimes I'm fumbling around with my phone and it takes me 20 seconds just to unlock the thing. Would it make sense to give them, say, 1 min, after which we could offer someway to resend the permission request? |
Yeah I was thinking something like this. The current UI has links like "I don't have access to my phone right now". So I think these sorts of things should actually be dealt with at the UI layer not automatically in the store. |
0aab026
to
9a56f30
Compare
@@ -27,21 +27,30 @@ export const setupWpDataDebug = () => { | |||
Site.register( clientCreds ); | |||
|
|||
window.wp.auth = {}; | |||
let previousState = window.wp?.data.select( AUTH_STORE ).getLoginFlowState(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A question, because I'm not sure...
Does the optional chaining inwindow.wp?
makes sense seeing as, in the line above we're assuming that wp
is a property of window
anyway? (window.wp.auth = {};
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eagle eyes! No they're not needed, just a copy paste bug from when I copied code from inside the callback.
It is needed inside the callback because window.wp
could be undefined
again by the time the callback is called (according to the type checker). Given it's just devtools it's a case of do-what-you-need-to-do-to-shut-the-type-checker-up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is working great for me now @p-jackson, I really like the elegant approach of handling both the wait
and cancelling an existing poll via task ids. From testing in the console, it correctly errors out and stops polling when push authentication has been throttled, too.
Just left a couple of notes of tiny typos, but once they're fixed up, it's looking good to go to me!
Thanks for the reviews. Merging to wrap up this round of the auth store work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work on all this! 🚢
Changes proposed in this Pull Request
/log-in
)downlevelIteration
to TS config so we can useyield*
in generator functions"Push" means when we send a push notification to the WordPress app during login, and you click the button in the app to approve the login. Not the one where you have to end a code for the 2nd factor.
Testing instructions
wp.auth.submitUsernameOrEmail('username')
using an account that's logged into the mobile appwp.auth.submitPassword('correctpassword')
wp.auth.reset()
while polling is happening, polling should stopShould probably try a passwordless account with 2fa. I don't actually know if passwordless accounts can have a second factor 🤔 (we might ask them to pick a password)