From f6c1f0f08f031778a491465d35ac694bfcdc12b0 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 1 Aug 2026 01:10:35 +0200 Subject: Require a fresh second factor for user management Administrative actions are gated behind a 30-minute elevation window: creating and retiring accounts, editing roles, clearing a second factor. Reading the list is not gated, and content work is untouched. elevated? is tied to is_admin?, so losing the role closes the window at once. The window opens when the second factor verifies at login, so an admin heading straight for user management is already elevated, and closes on logout with the other session state. Five wrong codes end the session, mirroring the login challenge. users#update carries no elevation filter, since self-service reaches it; the role field is gated in user_params instead and fails closed. --- app/views/elevations/new.html.erb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 app/views/elevations/new.html.erb (limited to 'app/views/elevations') diff --git a/app/views/elevations/new.html.erb b/app/views/elevations/new.html.erb new file mode 100644 index 00000000..1091ff36 --- /dev/null +++ b/app/views/elevations/new.html.erb @@ -0,0 +1,23 @@ +

<%= t(".title") %>

+ +
+ <% if current_user.otp_enrolled? %> +

+ <%= t(".hint", :minutes => AuthenticatedSystem::ELEVATION_MAX_AGE.in_minutes.to_i) %> +

+ <%= form_tag elevation_path do %> +
<%= t(".code") %>
+
+ <%= text_field_tag :code, nil, :autocomplete => "one-time-code", + :inputmode => "numeric", :autofocus => true %> +
+
+
<%= submit_tag t(".elevate") %>
+ <% end %> + <% else %> + <%# An admin without an enrolled factor cannot elevate at all. Say so and + point at enrolment rather than showing a field that cannot work. %> +

<%= t(".not_enrolled") %>

+ <%= link_to t(".enrol"), otp_enrollment_path, :class => "action_button" %> + <% end %> +
-- cgit v1.3