[FIX] Webauthn security key fixes after real-world usage (#8135)

[FIX] Webauthn security key fixes after real-world usage (#8135)

  • Fix broken security key 2FA on mobile login.hbs

  • Show nicer error message when a security key already exists

  • [COPY] Disable -> Delete for security key editing

  • Standardize UI elements in 2FA prefs password confirmation

  • Minor fixes to label location for resetPasswordProgress

diff --git a/app/assets/javascripts/discourse/controllers/second-factor-add-security-key.js.es6 b/app/assets/javascripts/discourse/controllers/second-factor-add-security-key.js.es6
index 6106d26..4d61400 100644
--- a/app/assets/javascripts/discourse/controllers/second-factor-add-security-key.js.es6
+++ b/app/assets/javascripts/discourse/controllers/second-factor-add-security-key.js.es6
@@ -109,6 +109,12 @@ export default Ember.Controller.extend(ModalFunctionality, {
               .finally(() => this.set("loading", false));
           },
           err => {
+            if (err.name === "InvalidStateError") {
+              return this.set(
+                "errorMessage",
+                I18n.t("user.second_factor.security_key.already_added_error")
+              );
+            }
             if (err.name === "NotAllowedError") {
               return this.set(
                 "errorMessage",
diff --git a/app/assets/javascripts/discourse/templates/components/cancel-link.hbs b/app/assets/javascripts/discourse/templates/components/cancel-link.hbs
index 8c3a3cb..4455e8b 100644
--- a/app/assets/javascripts/discourse/templates/components/cancel-link.hbs
+++ b/app/assets/javascripts/discourse/templates/components/cancel-link.hbs
@@ -1,3 +1,3 @@
-{{#link-to route args}}
+{{#link-to route args class="cancel"}}
   {{i18n 'cancel'}}
 {{/link-to}}
diff --git a/app/assets/javascripts/discourse/templates/mobile/modal/login.hbs b/app/assets/javascripts/discourse/templates/mobile/modal/login.hbs
index 594ea48..49ac40c 100644
--- a/app/assets/javascripts/discourse/templates/mobile/modal/login.hbs
+++ b/app/assets/javascripts/discourse/templates/mobile/modal/login.hbs
@@ -40,8 +40,21 @@
           secondFactorMethod=secondFactorMethod
           secondFactorToken=secondFactorToken
           class=secondFactorClass
+          backupEnabled=backupEnabled
           isLogin=true}}
-          {{second-factor-input value=secondFactorToken inputId='login-second-factor' secondFactorMethod=secondFactorMethod backupEnabled=backupEnabled}}
+          {{#if showSecurityKey}}
+            {{#security-key-form
+              allowedCredentialIds=securityKeyAllowedCredentialIds
+              challenge=securityKeyChallenge
+              showSecurityKey=showSecurityKey
+              showSecondFactor=showSecondFactor
+              secondFactorMethod=secondFactorMethod
+              otherMethodAllowed=secondFactorRequired
+              action=(action "authenticateSecurityKey")}}
+            {{/security-key-form}}
+          {{else}}
+            {{second-factor-input value=secondFactorToken inputId='login-second-factor' secondFactorMethod=secondFactorMethod backupEnabled=backupEnabled}}
+          {{/if}}
         {{/second-factor-form}}
       </form>
     {{/if}}
@@ -54,11 +67,13 @@
     {{/if}}
 
     {{#if canLoginLocal}}
-      {{d-button action=(action "login")
-        icon="unlock"
-        label=loginButtonLabel
-        disabled=loginDisabled
-        class="btn btn-large btn-primary"}}
+      {{#unless showSecurityKey }}
+        {{d-button action=(action "login")
+          icon="unlock"
+          label=loginButtonLabel
+          disabled=loginDisabled
+          class="btn btn-large btn-primary"}}
+      {{/unless}}
 
       {{#if showSignupLink}}
         {{#d-button class="btn btn-large" id="new-account-link" action=(route-action "showCreateAccount")}}
diff --git a/app/assets/javascripts/discourse/templates/modal/second-factor-edit-security-key.hbs b/app/assets/javascripts/discourse/templates/modal/second-factor-edit-security-key.hbs
index 5bfaa9b..7de9e5a 100644
--- a/app/assets/javascripts/discourse/templates/modal/second-factor-edit-security-key.hbs
+++ b/app/assets/javascripts/discourse/templates/modal/second-factor-edit-security-key.hbs
@@ -11,5 +11,5 @@
 
   {{d-button action=(action "disableSecurityKey")
     class="btn-danger"
-    label="user.second_factor.security_key.disable"}}
+    label="user.second_factor.security_key.delete"}}
 {{/d-modal-body}}
diff --git a/app/assets/javascripts/discourse/templates/preferences-second-factor.hbs b/app/assets/javascripts/discourse/templates/preferences-second-factor.hbs
index 7bacef4..1b6bb0d 100644
--- a/app/assets/javascripts/discourse/templates/preferences-second-factor.hbs
+++ b/app/assets/javascripts/discourse/templates/preferences-second-factor.hbs
@@ -126,7 +126,7 @@
             {{text-field value=password
               id="password"
               type="password"
-              classNames="input-xxlarge"
+              classNames="input-large"
               autofocus="autofocus"}}
           </div>
           <div class='instructions'>
@@ -142,16 +142,14 @@
             disabled=loading
             label="continue"}}
 
-          {{d-button action=(action "resetPassword")
-            class="btn"
-            disabled=resetPasswordLoading
-            icon="envelope"
-            label='user.change_password.action'}}
-
-          {{resetPasswordProgress}}
-
           {{#unless showEnforcedNotice}}
-            {{cancel-link route="preferences.account" args= model.username}}
+            {{cancel-link route="preferences.account" args=model.username}}
+          {{/unless}}
+        </div>
+        <div class="controls" style="margin-top: 5px">
+          {{resetPasswordProgress}}
+          {{#unless resetPasswordLoading}}
+            <a href="" class="instructions" {{action "resetPassword"}}>{{ i18n 'user.second_factor.forgot_password' }}</a>
           {{/unless}}
         </div>
       </div>
diff --git a/app/assets/stylesheets/common/base/discourse.scss b/app/assets/stylesheets/common/base/discourse.scss
index 31425a7..d436650 100644
--- a/app/assets/stylesheets/common/base/discourse.scss
+++ b/app/assets/stylesheets/common/base/discourse.scss
@@ -120,6 +120,16 @@ button {
   }
 }
 
+a.cancel {
+  margin-left: 1.25em;
+  line-height: normal;
+  color: $primary-high;
+  transition: color 250ms;
+  &:hover {
+    color: $danger;
+  }
+}
+
 ul.breadcrumb {
   margin: 0 10px 0 10px;
 }
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 0193253..ab50d17 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -969,6 +969,7 @@ en:
       second_factor:
         title: "Two Factor Authentication"
         enable: "Manage Two Factor Authentication"
+        forgot_password: "Forgot password?"
         confirm_password_description: "Please confirm your password to continue"
         label: "Code"
         rate_limit: "Please wait before trying another authentication code."
@@ -1000,9 +1001,10 @@ en:
           add: "Register Security Key"
           default_name: "Main Security Key"
           not_allowed_error: "The security key registration process either timed out or was cancelled."
+          already_added_error: "You have already registered this security key. You don’t have to register it again."
           edit: 'Edit Security Key'
           edit_description: 'Security Key Name'
-          disable: 'Disable'
+          delete: 'Delete'
 
       change_about:
         title: "Change About Me"

GitHub sha: 9f5ec715