diff --git a/app/services/webauthn/authenticate_service.rb b/app/services/webauthn/authenticate_service.rb
index a575a853995d046bcd54dc9ac5d46e5ee613a96e..52437a77df8bc2dc2a7295724e31d14ab5704718 100644
--- a/app/services/webauthn/authenticate_service.rb
+++ b/app/services/webauthn/authenticate_service.rb
@@ -30,6 +30,8 @@ def execute
       false
     end
 
+    private
+
     ##
     # Validates that webauthn_credential is syntactically valid
     #
diff --git a/spec/models/u2f_registration_spec.rb b/spec/models/u2f_registration_spec.rb
index 027d26d965732e0d3a953c17b1c067a70339bd90..1fab3882c2ade338dc6f020bf4d14ece8221444b 100644
--- a/spec/models/u2f_registration_spec.rb
+++ b/spec/models/u2f_registration_spec.rb
@@ -6,21 +6,67 @@
   let_it_be(:user) { create(:user) }
 
   let(:u2f_registration_name) { 'u2f_device' }
-  let(:u2f_registration) do
-    device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
-    create(
-      :u2f_registration, name: u2f_registration_name,
-      user: user,
-      certificate: Base64.strict_encode64(device.cert_raw),
-      key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
-      public_key: Base64.strict_encode64(device.origin_public_key_raw)
-    )
+  let(:app_id) { FFaker::BaconIpsum.characters(5) }
+  let(:device) { U2F::FakeU2F.new(app_id) }
+
+  describe '.authenticate' do
+    context 'when registration is found' do
+      it 'returns true' do
+        create_u2f_registration
+        device_challenge = U2F.urlsafe_encode64(SecureRandom.random_bytes(32))
+        sign_response_json = device.sign_response(device_challenge)
+
+        response = U2fRegistration.authenticate(
+          user,
+          app_id,
+          sign_response_json,
+          device_challenge
+        )
+
+        expect(response).to eq true
+      end
+    end
+
+    context 'when registration not found' do
+      it 'returns nil' do
+        device_challenge = U2F.urlsafe_encode64(SecureRandom.random_bytes(32))
+        sign_response_json = device.sign_response(device_challenge)
+
+        # data is valid but user does not have any u2f_registrations
+        response = U2fRegistration.authenticate(
+          user,
+          app_id,
+          sign_response_json,
+          device_challenge
+        )
+
+        expect(response).to eq nil
+      end
+    end
+
+    context 'when args passed in are invalid' do
+      it 'returns false' do
+        some_app_id = 123
+        invalid_json = 'invalid JSON'
+        challenges = 'whatever'
+
+        response = U2fRegistration.authenticate(
+          user,
+          some_app_id,
+          invalid_json,
+          challenges
+        )
+
+        expect(response).to eq false
+      end
+    end
   end
 
   describe 'callbacks' do
     describe 'after create' do
       shared_examples_for 'creates webauthn registration' do
         it 'creates webauthn registration' do
+          u2f_registration = create_u2f_registration
           webauthn_registration = WebauthnRegistration.where(u2f_registration_id: u2f_registration.id)
           expect(webauthn_registration).to exist
         end
@@ -51,13 +97,14 @@
           receive(:track_exception).with(kind_of(StandardError),
                                              u2f_registration_id: 123))
 
-        u2f_registration
+        create_u2f_registration
       end
     end
 
     describe 'after update' do
       context 'when counter is updated' do
         it 'updates the webauthn registration counter to be the same value' do
+          u2f_registration = create_u2f_registration
           new_counter = u2f_registration.counter + 1
           webauthn_registration = WebauthnRegistration.find_by(u2f_registration_id: u2f_registration.id)
 
@@ -70,6 +117,7 @@
 
       context 'when sign count of registration is not updated' do
         it 'does not update the counter' do
+          u2f_registration = create_u2f_registration
           webauthn_registration = WebauthnRegistration.find_by(u2f_registration_id: u2f_registration.id)
 
           expect do
@@ -79,4 +127,15 @@
       end
     end
   end
+
+  def create_u2f_registration
+    create(
+      :u2f_registration,
+      name: u2f_registration_name,
+      user: user,
+      certificate: Base64.strict_encode64(device.cert_raw),
+      key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+      public_key: Base64.strict_encode64(device.origin_public_key_raw)
+    )
+  end
 end
diff --git a/spec/services/webauthn/authenticate_service_spec.rb b/spec/services/webauthn/authenticate_service_spec.rb
index 61f64f24f5e78e165e39855b8bd79665b2e1670c..b40f9465b635e967e8a11c4191483736eae08144 100644
--- a/spec/services/webauthn/authenticate_service_spec.rb
+++ b/spec/services/webauthn/authenticate_service_spec.rb
@@ -30,19 +30,28 @@
       get_result['clientExtensionResults'] = {}
       service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
 
-      expect(service.execute).to be_truthy
+      expect(service.execute).to eq true
     end
 
-    it 'returns false if the response is valid but no matching stored credential is present' do
-      other_client = WebAuthn::FakeClient.new(origin)
-      other_client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
+    context 'when response is valid but no matching stored credential is present' do
+      it 'returns false' do
+        other_client = WebAuthn::FakeClient.new(origin)
+        other_client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
 
-      get_result = other_client.get(challenge: challenge)
+        get_result = other_client.get(challenge: challenge)
 
-      get_result['clientExtensionResults'] = {}
-      service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
+        get_result['clientExtensionResults'] = {}
+        service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
+
+        expect(service.execute).to eq false
+      end
+    end
 
-      expect(service.execute).to be_falsey
+    context 'when device response includes invalid json' do
+      it 'returns false' do
+        service = Webauthn::AuthenticateService.new(user, 'invalid JSON', '')
+        expect(service.execute).to eq false
+      end
     end
   end
 end