Problem/Motivation

When the full-setup flow produces more than one step — a validation plugin plus at least one @TfaLogin plugin (e.g. tfa_trusted_browser) — the "Skip" / "Skip and finish" button cancels the entire setup instead of skipping the current step and finishing. In TfaSetupForm::buildForm() the skip button carries '#submit' => ['::cancelForm']:

$form['actions']['skip'] = [
  '#type' => 'submit',
  '#value' => $count > 0 ? $this->t('Skip') : $this->t('Skip and finish'),
  '#limit_validation_errors' => [],
  '#submit' => ['::cancelForm'],
];

So pressing it runs cancelForm() ("Setup of ... canceled.") and aborts the whole setup. The dedicated skip branch already present in submitForm() (isset($values['skip']) && $values['op'] === $values['skip']) is therefore dead code and never runs.

Steps to reproduce

Reproduced on 8.x-1.12 (the same code is present on 8.x-1.x) with:

  • default_validation_plugin: tfa_totp
  • login_plugins: { tfa_trusted_browser }

which yields the two-step sequence [tfa_totp, tfa_trusted_browser].

Precondition: the multi-step path is only reachable once the setup-plugin re-resolve bug (#3451488, MR !163) is fixed — on a pristine build the user never advances past the first (TOTP) step, so this bug is not observable. Apply MR !163 first, then use the configuration above.

  1. As a fresh user with no TFA configured, open /user/{uid}/security/tfa/tfa_totp and confirm the current password.
  2. Scan the QR code, enter the 6-digit code, press "Verify and save" — you are advanced to the "Trust this browser" step.
  3. Press "Skip and finish".

Observed: "Setup of ... canceled." and the whole setup is aborted, instead of skipping the trusted-browser step and finishing with TFA (TOTP) enabled.

Expected: "Skip and finish" completes the setup with the already-configured plugin(s) enabled.

Proposed resolution

Remove the '#submit' override (keep '#limit_validation_errors' => []) so the button falls through to the default submitForm() and hits the existing skip branch. Even with limited validation the triggering button value is still preserved under both $values['op'] and $values['skip'] (core Button #name defaults to 'op'; FormValidator::handleErrorsWithLimitedValidation() writes the triggering element's #value back to both #parents and #name), so the strict comparison in the skip branch holds. The separate "Cancel" button on the first/single step keeps ::cancelForm.

$form['actions']['skip'] = [
  '#type' => 'submit',
  '#value' => $count > 0 ? $this->t('Skip') : $this->t('Skip and finish'),
  '#limit_validation_errors' => [],
];

Remaining tasks

  • Review the MR.
  • Confirm ordering against #3451488 / MR !163 — that fix is a precondition for reaching the step where this button appears.

User interface changes

No layout changes. Behavioural only: at a non-first step, "Skip and finish" now completes setup instead of showing "Setup of ... canceled.".

API changes

None.

Data model changes

None.

Issue fork tfa-3611367

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

poliphilochu created an issue. See original summary.

poliphilochu’s picture

Status: Active » Needs review
StatusFileSize
new1.56 KB

Attaching a patch against 8.x-1.12 that covers all three bugs from the issue
summary.

Reproduction note: the multi-step path is only reachable after the setup-plugin
re-resolve fix from #3451488 (MR !163) is applied (see Steps to reproduce). On a
pristine 8.x-1.12 the user never advances past the first step, so none of the
three bugs are observable without it.

cmlara’s picture

Version: 8.x-1.12 » 8.x-1.x-dev

I'm going to have to look close, though I believe we might have issue already open for some of these (or at least someone mentioned them at some time and they needed followups). Leaving open as I haven't confirmed existing issues exist.

Email send might be related to https://www.drupal.org/project/tfa/issues/3424052

It would be helpful if these are separate issues per bug (unless the code is the exact same code to fix all of them).

the multi-step path is only reachable once the setup-plugin re-resolve bug (#3451488, MR !163) is fixed

That may mean some of this belongs in that issue as related to the current feature not working

the enabled-plugins list in tfa_user_settings ends up missing the actual validation plugin (e.g. tfa_totp). The TOTP seed is stored and the user can pass 2FA at login, but the profile's enabled plugins never include tfa_totp.

Interesting, that may be another path where at times years ago I would see the database be out of sync raising questions and previously leading to being unable to trust the user settings.

Addtionaly as a note patch workflows are outdated, MR's allow easier access to review the code in context with its other changes as well as running pipelines to evaluate structural syntax.

poliphilochu’s picture

Title: Multi-step full setup is broken: "Skip and finish" cancels setup, completion fires prematurely (duplicate email), and the validation plugin is missing from enabled plugins » "Skip and finish" cancels the whole setup instead of skipping the step and finishing
Issue summary: View changes
Related issues: -#3369086: TFA enabled config not set on user profile, -#3386346: tfa_user_settings not updated when enabeling new plugin

poliphilochu’s picture

Thanks @cmlara for the quick triage.

I've re-scoped this issue (#3611367) down to just the "Skip and finish"
cancels-setup bug, and opened separate issues for the other two:

  • #3612129: full-setup completion fires on every step, so the "setup complete" message and the notification email are sent once per step instead of once.
  • #3612130: full setup records only the last step, so the validation plugin (e.g. tfa_totp) is missing from the enabled plugins in tfa_user_settings.

I did search the queue before filing and didn't find existing open issues for
these two specific root causes (only #3424052, which is related but different -
see below). If you find you already have issues open for either, point me at
them and I'll consolidate rather than leave duplicates.

On the email: it's related to #3424052 but a different mechanism. #3424052
filters the email by plugin type (don't email for login plugins). What I'm
seeing is that the multi-step early-return in submitForm() is broken - it checks
$form_state->getRebuildInfo() (the rebuild_info property) instead of
$form_state->isRebuilding() (the rebuild property set by setRebuild()).
getRebuildInfo() is always empty here, so the whole completion block - status
message, tfaSaveTfaData(), and the email - runs once per step, not just the
email. The two fixes are complementary; I've cross-linked them on #3612129
rather than duplicating.

Fair point, since all of this is only reachable once the setup-plugin
re-resolve bug (#3451488 / MR !163) is fixed (on a pristine build the user
never advances past the first step), they are in a sense all part of "full
setup" working end to end. I've kept them as separate issues rather than folding
into #3451488 for two reasons: each is an independent fix in a different part of
the form, and #3451488 / MR !163 is narrowly scoped to the re-resolve and close
to review - piling three more fixes onto it would muddy that. All three list
#3451488 as related and note it as a precondition in their steps to reproduce.
That said, if you'd rather track them under #3451488 as the feature-level issue,
I'm happy to move them.

cmlara’s picture

Status: Needs review » Postponed

Postponed on #3451488