@@ -164,6 +164,60 @@ def generate_assertion(fake_client, challenge:, credential:)
164164 expect ( controller . current_account ) . to be_nil
165165 end
166166
167+ it "completes authentication when userHandle matches the authenticated user" do
168+ post account_session_path , params : { account : { email : user . email , password : password } }
169+
170+ expect ( response ) . to redirect_to ( new_account_two_factor_authentication_path )
171+
172+ follow_redirect!
173+
174+ expect ( response ) . to have_http_status ( :ok )
175+ get account_security_key_authentication_options_path
176+
177+ assertion = client . get (
178+ challenge : session [ :two_factor_authentication_challenge ] ,
179+ allow_credentials : [ security_key . external_id ] ,
180+ user_handle : WebAuthn . configuration . encoder . decode ( user . webauthn_id )
181+ )
182+
183+ expect do
184+ post account_two_factor_authentication_path , params : {
185+ public_key_credential : assertion . to_json
186+ }
187+
188+ expect ( response ) . to redirect_to ( root_path )
189+ expect ( controller . current_account ) . to eq ( user )
190+ end . to change { security_key . reload . sign_count } . by ( 1 )
191+ end
192+
193+ it "rejects 2FA when userHandle does not match the authenticated user" do
194+ other_user = Account . create! ( email : "other@example.com" , password : password )
195+
196+ post account_session_path , params : { account : { email : user . email , password : password } }
197+
198+ expect ( response ) . to redirect_to ( new_account_two_factor_authentication_path )
199+
200+ follow_redirect!
201+
202+ expect ( response ) . to have_http_status ( :ok )
203+ get account_security_key_authentication_options_path
204+
205+ assertion = client . get (
206+ challenge : session [ :two_factor_authentication_challenge ] ,
207+ allow_credentials : [ security_key . external_id ] ,
208+ user_handle : WebAuthn . configuration . encoder . decode ( other_user . webauthn_id )
209+ )
210+
211+ post account_two_factor_authentication_path , params : {
212+ public_key_credential : assertion . to_json
213+ }
214+
215+ expect ( response ) . to have_http_status ( :unprocessable_entity )
216+ expect ( response . body ) . to include ( "Use security key" )
217+ expect ( flash [ :alert ] ) . to eq ( I18n . t ( "devise.failure.webauthn_credential_verification_failed" ) )
218+ expect ( controller . current_account ) . to be_nil
219+ end
220+
167221 it "re-renders 2FA page when credential param is missing" do
168222 post account_session_path , params : { account : { email : user . email , password : password } }
169223
0 commit comments