FIX: Ensure enforce 2FA for staff satisfied by security keys (#8316)

FIX: Ensure enforce 2FA for staff satisfied by security keys (#8316)

  • If a staff user created only a security key as their single 2FA option. they continued to be prompted to create a 2FA option because we only considered this condition satisfied if a TOTP was added.
  • The condition is now satisfied if TOTP OR security keys are enabled.
diff --git a/app/serializers/admin_detailed_user_serializer.rb b/app/serializers/admin_detailed_user_serializer.rb
index 3555522497..4a83a594b1 100644
--- a/app/serializers/admin_detailed_user_serializer.rb
+++ b/app/serializers/admin_detailed_user_serializer.rb
@@ -39,7 +39,7 @@ class AdminDetailedUserSerializer < AdminUserSerializer
   has_many :groups, embed: :object, serializer: BasicGroupSerializer
 
   def second_factor_enabled
-    object.totp_enabled?
+    object.totp_enabled? || object.security_keys_enabled?
   end
 
   def can_disable_second_factor
diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb
index 4ba1a982f8..72363fc3ac 100644
--- a/app/serializers/current_user_serializer.rb
+++ b/app/serializers/current_user_serializer.rb
@@ -210,6 +210,6 @@ class CurrentUserSerializer < BasicUserSerializer
   end
 
   def second_factor_enabled
-    object.totp_enabled?
+    object.totp_enabled? || object.security_keys_enabled?
   end
 end
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index 52d1214cfd..79111200ef 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -164,7 +164,7 @@ class UserSerializer < BasicUserSerializer
   end
 
   def second_factor_enabled
-    object.totp_enabled?
+    object.totp_enabled? || object.security_keys_enabled?
   end
 
   def include_second_factor_backup_enabled?
diff --git a/spec/serializers/current_user_serializer_spec.rb b/spec/serializers/current_user_serializer_spec.rb
index 9eb2d34c62..30c6a40497 100644
--- a/spec/serializers/current_user_serializer_spec.rb
+++ b/spec/serializers/current_user_serializer_spec.rb
@@ -68,6 +68,38 @@ RSpec.describe CurrentUserSerializer do
     end
   end
 
+  context "#second_factor_enabled" do
+    fab!(:user) { Fabricate(:user) }
+    let :serializer do
+      CurrentUserSerializer.new(user, scope: Guardian.new(user), root: false)
+    end
+    let(:json) { serializer.as_json }
+
+    it "is false by default" do
+      expect(json[:second_factor_enabled]).to eq(false)
+    end
+
+    context "when totp enabled" do
+      before do
+        User.any_instance.stubs(:totp_enabled?).returns(true)
+      end
+
+      it "is true" do
+        expect(json[:second_factor_enabled]).to eq(true)
+      end
+    end
+
+    context "when security_keys enabled" do
+      before do
+        User.any_instance.stubs(:security_keys_enabled?).returns(true)
+      end
+
+      it "is true" do
+        expect(json[:second_factor_enabled]).to eq(true)
+      end
+    end
+  end
+
   context "#groups" do
     fab!(:member) { Fabricate(:user) }
     let :serializer do
diff --git a/spec/serializers/user_serializer_spec.rb b/spec/serializers/user_serializer_spec.rb
index 262166422a..fbe25589db 100644
--- a/spec/serializers/user_serializer_spec.rb
+++ b/spec/serializers/user_serializer_spec.rb
@@ -40,8 +40,9 @@ describe UserSerializer do
   end
 
   context "with a user" do
+    let(:scope) { Guardian.new }
     fab!(:user) { Fabricate(:user) }
-    let(:serializer) { UserSerializer.new(user, scope: Guardian.new, root: false) }
+    let(:serializer) { UserSerializer.new(user, scope: scope, root: false) }
     let(:json) { serializer.as_json }
     fab!(:upload) { Fabricate(:upload) }
     fab!(:upload2) { Fabricate(:upload) }
@@ -164,6 +165,33 @@ describe UserSerializer do
         expect(json[:bio_cooked]).to eq 'my cooked bio'
       end
     end
+
+    describe "second_factor_enabled" do
+      let(:scope) { Guardian.new(user) }
+      it "is false by default" do
+        expect(json[:second_factor_enabled]).to eq(false)
+      end
+
+      context "when totp enabled" do
+        before do
+          User.any_instance.stubs(:totp_enabled?).returns(true)
+        end
+
+        it "is true" do
+          expect(json[:second_factor_enabled]).to eq(true)
+        end
+      end
+
+      context "when security_keys enabled" do
+        before do
+          User.any_instance.stubs(:security_keys_enabled?).returns(true)
+        end
+
+        it "is true" do
+          expect(json[:second_factor_enabled]).to eq(true)
+        end
+      end
+    end
   end
 
   context "with custom_fields" do

GitHub sha: 64b4a7ba

1 Like