[6.x] Modernize elevated sessions#19238
Open
brianjhanson wants to merge 10 commits into
Open
Conversation
📚 Storybook previews@craftcms/cp — open Storybook No changed components detected in this Storybook. resources/js — open Storybook No changed components detected in this Storybook. |
Pulled in the colleague's elevated-session work and made it the base, since it is comprehensively more complete than our branch: - Vue-native modal (ElevatedSessionHost.vue) with real 2FA/passkey support via the server-captured cp.login.alternative-login-methods fragment, replacing our reuse of the legacy jQuery/Garnish login modal. - Server enforcement: 423 status, RequireConfirmedPassword middleware (password.confirm alias), dedicated users/confirm-password endpoint. - Reactive manager + both proactive (passwordConfirmation.required) and server-reactive (423 retry) triggers; LoginRateLimiter; comprehensive tests. Reconciliation (favoring the better bit from each branch): - Removed our superseded parallel module (resources/js/modules/elevated-session, common/composables/useElevatedSession) and its useSettingsSave elevatedFields API in favor of theirs. - Kept our cleanup instinct: deleted the now-orphaned legacy JS — both ElevatedSessionForm.js (already removed on our side) and ElevatedSessionManager.js (left dangling/unimported on theirs). - Added a root `vitest` runner (test script + happy-dom test block in vite.config.js) so their new resources/js/**/*.test.ts suites actually run; they had no configured project and would otherwise never execute. Verified: vue-tsc 0 errors, eslint 0 errors, vite build ok, 26 frontend tests pass, and elevated-session + login/provider Pest suites pass on a built DB. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The skip-link token renames and permissions heading margin tweak that landed in "First run through" are unrelated to the elevated-session work; they've been split out to the design-token-updates branch (off 6.x). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
riasvdv
approved these changes
Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requires a user to re-confirm their password (an "elevated session") before a sensitive change goes through — toggling admin, granting new permissions/groups, changing a password, revealing a GraphQL token, and so on.
Replaces the legacy jQuery/Garnish login modal with a Vue-native confirmation flow, and enforces elevation server-side:
RequireConfirmedPasswordmiddleware (password.confirmalias) +ConfirmsPasswords::requireConfirmedPassword()return 423 when elevation is missing; a dedicatedusers/confirm-passwordendpoint drives the modal.elevatedSessionManager+<ElevatedSessionHost>modal (with 2FA / passkey fallbacks). Works both proactively (prompt before submit) and reactively (retry once on a 423).Craft.ElevatedSessionFormandCraft.elevatedSessionManagerare shimmed onto the new code, so existing Twig screens keep working. The module follows the standard main-class / custom-element / index-shim shape (likelistbox,generated-fields).Usage
Inertia form — require elevation only when sensitive fields changed:
One-off action — run a callback behind an elevated session (auto-retries on 423):
Legacy Twig form — declarative custom element (or the Craft.ElevatedSessionForm global):
Server enforcement — middleware or inline:
Fixes #19235