mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 13:39:44 +02:00
fix(editor): Flip to webauthn via switcher when MFA login defaults to TOTP
The seeded test owner has `mfaSecret` set (so `availableMfaMethods` includes 'totp' alongside webauthn) and the previous successful sign-in caches the chosen method in `localStorage.n8n.last2faMethod`. When the user lands back on the MFA prompt with `last = 'totp'`, the TOTP form shows instead of the webauthn prompt. The composable's `loginWithWebAuthn` now flips to the webauthn screen via the switcher when it detects the TOTP form. Also wraps the TOTP branch of `MfaView` in `mfa-totp-screen` so the page object can scope the switcher locator without tripping the janitor's `scope-lockdown` rule.
This commit is contained in:
parent
9c8f1000a7
commit
84bc17ab9f
|
|
@ -297,7 +297,7 @@ watch(currentMethod, (next) => {
|
|||
</div>
|
||||
|
||||
<!-- TOTP flow -->
|
||||
<template v-if="currentMethod === 'totp'">
|
||||
<div v-if="currentMethod === 'totp'" data-test-id="mfa-totp-screen">
|
||||
<div :class="[$style.formContainer, reportError ? $style.formError : '']">
|
||||
<N8nFormInputs
|
||||
v-if="formInputs"
|
||||
|
|
@ -362,7 +362,7 @@ watch(currentMethod, (next) => {
|
|||
{{ i18.baseText(switcherLabelKey) }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- WebAuthn flow (passkey or security key) -->
|
||||
<div v-else data-test-id="mfa-webauthn-screen">
|
||||
|
|
|
|||
|
|
@ -72,13 +72,20 @@ export class MfaComposer {
|
|||
/**
|
||||
* Complete the MFA login via a WebAuthn ceremony. The browser ceremony is
|
||||
* served by whichever virtual authenticator was attached to the page —
|
||||
* see `utils/webauthn-virtual-authenticator.ts`.
|
||||
* see `utils/webauthn-virtual-authenticator.ts`. If the MFA screen lands
|
||||
* on the TOTP form (which can happen when the seed user has both
|
||||
* `mfaSecret` and a webauthn credential, with `localStorage.n8n.last2faMethod`
|
||||
* pointing at `totp`), flip to webauthn via the switcher first.
|
||||
*/
|
||||
async loginWithWebAuthn(email: string, password: string): Promise<void> {
|
||||
await this.n8n.signIn.fillEmail(email);
|
||||
await this.n8n.signIn.fillPassword(password);
|
||||
await this.n8n.signIn.clickSubmit();
|
||||
|
||||
if (await this.n8n.mfaLogin.getForm().isVisible()) {
|
||||
await this.n8n.mfaLogin.getSwitcherLink().click();
|
||||
}
|
||||
|
||||
await this.n8n.mfaWebauthnLogin.clickWebAuthnButton();
|
||||
await expect(this.n8n.page).toHaveURL(/workflows/);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import { BasePage } from './BasePage';
|
|||
*/
|
||||
export class MfaLoginPage extends BasePage {
|
||||
get container(): Locator {
|
||||
return this.page.getByTestId('mfa-login-form');
|
||||
return this.page.getByTestId('mfa-totp-screen');
|
||||
}
|
||||
|
||||
getForm(): Locator {
|
||||
return this.container;
|
||||
return this.container.getByTestId('mfa-login-form');
|
||||
}
|
||||
|
||||
getMfaCodeField(): Locator {
|
||||
|
|
@ -52,4 +52,12 @@ export class MfaLoginPage extends BasePage {
|
|||
await this.fillMfaRecoveryCode(recoveryCode);
|
||||
// Form auto-submits
|
||||
}
|
||||
|
||||
/**
|
||||
* Switcher link shown when the user has both TOTP and a webauthn credential.
|
||||
* Clicking it flips the screen from TOTP to the webauthn prompt.
|
||||
*/
|
||||
getSwitcherLink(): Locator {
|
||||
return this.container.getByTestId('mfa-switcher').getByRole('button');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user