diff --git a/projects/orcid-ui-docs/src/app/app.routes.ts b/projects/orcid-ui-docs/src/app/app.routes.ts
index 626ed507ac..081114c591 100644
--- a/projects/orcid-ui-docs/src/app/app.routes.ts
+++ b/projects/orcid-ui-docs/src/app/app.routes.ts
@@ -93,6 +93,13 @@ export const routes: Routes = [
(m) => m.SkeletonPlaceholderPageComponent
),
},
+ {
+ path: 'step-view',
+ loadComponent: () =>
+ import('./pages/orcid-ui/step-view-page.component').then(
+ (m) => m.StepViewPageComponent
+ ),
+ },
{
path: 'auth-challenge',
loadComponent: () =>
diff --git a/projects/orcid-ui-docs/src/app/docs-shell.component.html b/projects/orcid-ui-docs/src/app/docs-shell.component.html
index df953dd98e..7a68d14b48 100644
--- a/projects/orcid-ui-docs/src/app/docs-shell.component.html
+++ b/projects/orcid-ui-docs/src/app/docs-shell.component.html
@@ -34,6 +34,7 @@
()
+}
diff --git a/projects/orcid-ui/src/public-api.ts b/projects/orcid-ui/src/public-api.ts
index 8c78466b78..2b9363cbfc 100644
--- a/projects/orcid-ui/src/public-api.ts
+++ b/projects/orcid-ui/src/public-api.ts
@@ -15,3 +15,4 @@ export * from './lib/components/action-surface-container/action-surface-containe
export * from './lib/components/panel/panel.component'
export * from './lib/components/skeleton-placeholder/skeleton-placeholder.component'
export * from './lib/components/modal/modal.component'
+export * from './lib/components/step-view/step-view.component'
diff --git a/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.html b/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.html
index 65af088a35..fa6dff8da7 100644
--- a/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.html
+++ b/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.html
@@ -11,40 +11,110 @@
Two-factor authentication was not disabled
- }
-
-
+ } @if (!twoFactorState) {
+
+
Add extra security to your ORCID account by enabling two-factor
authentication (2FA).
-
-
-
- Each time you sign in to ORCID you’ll be prompted to enter a six-digit
- code we send to your preferred 2FA authentication application.
-
-
-
-
- Two-factor authentication is currently:
-
-
-
- ON
- OFF
-
-
+ } @else {
+
+
+ Sign in with 2FA
+
+ Use your authentication app to generate a verification code whenever you
+ sign in to ORCID.
+
+
+
+ check_circle
+
+
+
+ Authentication app
+
+
+
+
+
+
+ Account recovery
+
+ Recover access to your ORCID account if you can't use your
+ authentication app.
+
+
+
+ check_circle
+
+
+
+ 2FA recovery codes
+
+
+
+
+
+
+ You can disable two-factor authentication at any time. Turning 2FA off
+ will reset any account recovery options you have set up.
+
+
+ Find out more about disabling two-factor authentication
+ open_in_new
+
+
+ Disable two-factor authentication
+
+
+ }
diff --git a/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.scss b/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.scss
index e69de29bb2..34e337e30e 100644
--- a/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.scss
+++ b/src/app/account-settings/components/settings-security-two-factor-auth/settings-security-two-factor-auth.component.scss
@@ -0,0 +1,80 @@
+.two-factor-panel {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.two-factor-panel--enabled {
+ gap: 24px;
+}
+
+.two-factor-panel__section {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ padding-bottom: 16px;
+ border-bottom: 1px solid #e0e0e0;
+}
+
+.two-factor-panel__section h4 {
+ margin: 0;
+ font-size: 16px;
+ line-height: 24px;
+}
+
+.two-factor-panel__section p {
+ margin: 0;
+}
+
+.two-factor-panel__copy {
+ margin: 0;
+}
+
+.two-factor-panel__copy--intro {
+ margin-top: var(--orcid-space-l, 32px);
+}
+
+.two-factor-panel__link {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ width: fit-content;
+ text-decoration: underline;
+}
+
+.two-factor-panel__link--disable-info {
+ margin-top: calc(var(--orcid-space-s, 8px) - var(--orcid-space-m, 24px));
+ margin-bottom: calc(var(--orcid-space-l, 32px) - var(--orcid-space-m, 24px));
+}
+
+.two-factor-panel__section-description {
+ margin-bottom: var(--orcid-space-m, 24px) !important;
+}
+
+.two-factor-panel__requirement {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ width: 100%;
+ border-top: 1px solid var(--orcid-color-border-subtle, #dddddd);
+ padding-top: 16px;
+}
+
+.two-factor-panel__requirement-title {
+ margin: 0;
+ font-weight: 700;
+}
+
+.two-factor-panel__requirement-icon {
+ color: var(--orcid-color-brand-primary-dark, #7faa26);
+ width: 24px;
+ height: 24px;
+ font-size: 24px;
+}
+
+.two-factor-panel__disable-button {
+ align-self: flex-start;
+ background: var(--orcid-color-state-warning-dark, #d32f2f) !important;
+ border-color: var(--orcid-color-state-warning-dark, #d32f2f) !important;
+ color: #fff !important;
+}
diff --git a/src/app/cdk/account-panel/settings-panels/settings-panels.component.scss b/src/app/cdk/account-panel/settings-panels/settings-panels.component.scss
index b89e3322d1..9c9716514f 100644
--- a/src/app/cdk/account-panel/settings-panels/settings-panels.component.scss
+++ b/src/app/cdk/account-panel/settings-panels/settings-panels.component.scss
@@ -39,6 +39,11 @@
strong {
margin-inline-end: 3px;
}
+
+ .on,
+ .off {
+ font-weight: 400;
+ }
}
.actions-container {
display: flex;
diff --git a/src/app/rum/app-event-names.ts b/src/app/rum/app-event-names.ts
index fd90aeb33f..990b93c43f 100644
--- a/src/app/rum/app-event-names.ts
+++ b/src/app/rum/app-event-names.ts
@@ -17,6 +17,10 @@ export enum AppEventName {
SignInFailure = 'sign_in_failure',
/** HTTP/network failure on sign-in POST (distinct from application-level sign_in_failure). */
SignInHttpError = 'sign_in_http_error',
+ TwoFactorSetupStep1Loaded = 'two_factor_setup_step1_loaded',
+ TwoFactorSetupStep2Loaded = 'two_factor_setup_step2_loaded',
+ TwoFactorSetupFinalButtonClicked = 'two_factor_setup_final_button_clicked',
+ TwoFactorSetupFinalCompleted = 'two_factor_setup_final_completed',
// ─── Orcid registration journey events ─────────────────────────────────────
StepASignInButtonClicked = 'step-a-sign-in-button-clicked',
diff --git a/src/app/rum/terminating-rum-events.ts b/src/app/rum/terminating-rum-events.ts
index dc519b03fb..fed1708840 100644
--- a/src/app/rum/terminating-rum-events.ts
+++ b/src/app/rum/terminating-rum-events.ts
@@ -27,6 +27,7 @@ export const TERMINATING_SIMPLE_EVENT_NAMES: ReadonlySet
= new Set([
AppEventName.SignInGuardRedirectToRegister,
AppEventName.SignInOauthInvalidGrantLegacy,
AppEventName.TwoFactorSignInGuardRedirectToMyOrcid,
+ AppEventName.TwoFactorSetupFinalCompleted,
AppEventName.RegisterGuardRedirectToAuthorize,
AppEventName.RegisterPipelineError,
AppEventName.OauthAuthorizationValidationFailed,
diff --git a/src/app/two-factor-setup/components/two-factor-enable/two-factor-enable.component.html b/src/app/two-factor-setup/components/two-factor-enable/two-factor-enable.component.html
index dca4214891..9e4f681e41 100644
--- a/src/app/two-factor-setup/components/two-factor-enable/two-factor-enable.component.html
+++ b/src/app/two-factor-setup/components/two-factor-enable/two-factor-enable.component.html
@@ -1,185 +1,136 @@