-
Notifications
You must be signed in to change notification settings - Fork 4.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
UI: allow retries for MFA form errors #27574
Conversation
CI Results: |
456306a
to
8e8ad5c
Compare
Build Results: |
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.
Incredibly diligence QA-ing and finding this bug! Just a question about whether the test passed or failed before when values ended in 0. (Mostly for curiosity sake)
@@ -173,9 +173,11 @@ module('Integration | Component | mfa-form', function (hooks) { | |||
// TODO JLR: It doesn't appear that cancelTimers is working and tests wait for the full countdown | |||
test('it should show countdown on passcode already used and rate limit errors', async function (assert) { | |||
const messages = { | |||
used: 'code already used; new code is available in 45 seconds', | |||
used: 'code already used; new code is available in 30 seconds', | |||
// there an intentional typo in the error message (30s seconds) |
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.
Thank you for this comment! "Typo" is a little ambiguous. I wonder if it's worth explicitly saying "the backend returns duplicate duration s" or something to make it clearer what the typo is?
Also, were you able to verify if this test failed or passed with the prior code when the seconds didn't end in 0? If so, it may be worth mentioning that somewhere that the regex didn't account for times ended in 0
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.
yep, the tests failed once i used the old regex. and i added a comment about the backend returning a duplicate string, thanks!
8e8ad5c
to
d06bea2
Compare
ui/app/components/mfa/mfa-form.js
Outdated
const delayRegExMatches = errorMessage.match(/(\d+\w seconds)/); | ||
if (delayRegExMatches) { | ||
delay = delayRegExMatches[0].split(' ')[0]; | ||
} else { | ||
// default to 30 seconds if no delay is found | ||
delay = 30; | ||
} | ||
this.countdown = parseInt(delay); |
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.
fixing this ding-dang regex was what resolved the bug 🙃
i also opted to add a safe default of 30s in case the API error message changes again too. it'll only apply if the error message contains the phrases from lines 89-90 above though, which will prevent us from adding a timeout if the API errors for an unrelated reason.
assert.dom('[data-test-mfa-validate]').isDisabled('Button is disabled during countdown'); | ||
assert.dom('[data-test-mfa-passcode]').isDisabled('Input is disabled during countdown'); | ||
assert.dom('[data-test-inline-error-message]').exists('Alert message renders'); | ||
} | ||
}); | ||
|
||
test('it defaults countdown to 30 seconds if error message does not indicate when user can try again ', async function (assert) { |
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.
test coverage for the default timeout that i added
// parse validity period from error string to initialize countdown | ||
this.countdown = parseInt(message.match(/(\d\w seconds)/)[0].split(' ')[0]); | ||
const delayRegExMatches = errorMessage.match(/(\d+\w seconds)/); |
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.
Great idea wrapping this in a conditional!
ui/app/components/mfa/mfa-form.js
Outdated
if (delayRegExMatches) { | ||
delay = delayRegExMatches[0].split(' ')[0]; | ||
} else { | ||
// default to 30 seconds if no delay is found |
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 also means we'll set a default if the parsed integer is 0. 🤔 I think this is okay...(I'm not sure a 0s period is even possible) Maybe adding to the comment here to remind future devs that this else block will also be hit if the delay is zero?
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.
fair point, i'll update the conditional to if (delayRegExMatches && delayRegExMatches.length)
to make that more explicit 😎
31d61fa
to
29a98ae
Compare
29a98ae
to
3b57f9c
Compare
🛠️ Description
Fixes a bug where the MFA form wasn't displaying an error message nor countdown when a user tried to enter an incorrect one-time password too many times.
Fixes JIRA ticket # VAULT-28437
📸 Screenshots
Before (notice missing error banner)
After (error banner & countdown shown, button disabled)
🏗️ How to Build and Test the Change
To replicate this you'll need to set up MFA and a userpass user. I recommend having two browser windows open: one for the
root
user and one for a userpass user.test
with all privileges (so the user can eventually enable MFA on their login):userpass
auth methodtest
policyVault
as the issuer (though it doesn't really matter). Enter 2 as the max validation attempts. Under Enforcements select "skip this step".60c04ac9-943b-79f6-f466-e1f1d2c2fe19
inmfa/methods/60c04ac9-943b-79f6-f466-e1f1d2c2fe19
TODO only if you're a HashiCorp employee
getting backported to N-2, use the new style
backport/ent/x.x.x+ent
labelsinstead of the old style
backport/x.x.x
labels.the normal
backport/x.x.x
label (there should be only 1).of a public function, even if that change is in a CE file, double check that
applying the patch for this PR to the ENT repo and running tests doesn't
break any tests. Sometimes ENT only tests rely on public functions in CE
files.
in the PR description, commit message, or branch name.
description. Also, make sure the changelog is in this PR, not in your ENT PR.