You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
6.5 KiB

Add WebAuthn as an alternative 2FA method (#14466) * feat: add possibility of adding WebAuthn security keys to use as 2FA This adds a basic UI for enabling WebAuthn 2FA. We did a little refactor to the Settings page for editing the 2FA methods – now it will list the methods that are available to the user (TOTP and WebAuthn) and from there they'll be able to add or remove any of them. Also, it's worth mentioning that for enabling WebAuthn it's required to have TOTP enabled, so the first time that you go to the 2FA Settings page, you'll be asked to set it up. This work was inspired by the one donde by Github in their platform, and despite it could be approached in different ways, we decided to go with this one given that we feel that this gives a great UX. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add request for WebAuthn as second factor at login if enabled This commits adds the feature for using WebAuthn as a second factor for login when enabled. If users have WebAuthn enabled, now a page requesting for the use of a WebAuthn credential for log in will appear, although a link redirecting to the old page for logging in using a two-factor code will also be present. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add possibility of deleting WebAuthn Credentials Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: disable WebAuthn when an Admin disables 2FA for a user Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: remove ability to disable TOTP leaving only WebAuthn as 2FA Following examples form other platforms like Github, we decided to make Webauthn 2FA secondary to 2FA with TOTP, so that we removed the possibility of removing TOTP authentication only, leaving users with just WEbAuthn as 2FA. Instead, users will have to click on 'Disable 2FA' in order to remove second factor auth. The reason for WebAuthn being secondary to TOPT is that in that way, users will still be able to log in using their code from their phone's application if they don't have their security keys with them – or maybe even lost them. * We had to change a little the flow for setting up TOTP, given that now it's possible to setting up again if you already had TOTP, in order to let users modify their authenticator app – given that now it's not possible for them to disable TOTP and set it up again with another authenticator app. So, basically, now instead of storing the new `otp_secret` in the user, we store it in the session until the process of set up is finished. This was because, as it was before, when users clicked on 'Edit' in the new two-factor methods lists page, but then went back without finishing the flow, their `otp_secret` had been changed therefore invalidating their previous authenticator app, making them unable to log in again using TOTP. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * refactor: fix eslint errors The PR build was failing given that linting returning some errors. This commit attempts to fix them. * refactor: normalize i18n translations The build was failing given that i18n translations files were not normalized. This commits fixes that. * refactor: avoid having the webauthn gem locked to a specific version * refactor: use symbols for routes without '/' * refactor: avoid sending webauthn disabled email when 2FA is disabled When an admins disable 2FA for users, we were sending two mails to them, one notifying that 2FA was disabled and the other to notify that WebAuthn was disabled. As the second one is redundant since the first email includes it, we can remove it and send just one email to users. * refactor: avoid creating new env variable for webauthn_origin config * refactor: improve flash error messages for webauthn pages Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com>
4 years ago
Add WebAuthn as an alternative 2FA method (#14466) * feat: add possibility of adding WebAuthn security keys to use as 2FA This adds a basic UI for enabling WebAuthn 2FA. We did a little refactor to the Settings page for editing the 2FA methods – now it will list the methods that are available to the user (TOTP and WebAuthn) and from there they'll be able to add or remove any of them. Also, it's worth mentioning that for enabling WebAuthn it's required to have TOTP enabled, so the first time that you go to the 2FA Settings page, you'll be asked to set it up. This work was inspired by the one donde by Github in their platform, and despite it could be approached in different ways, we decided to go with this one given that we feel that this gives a great UX. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add request for WebAuthn as second factor at login if enabled This commits adds the feature for using WebAuthn as a second factor for login when enabled. If users have WebAuthn enabled, now a page requesting for the use of a WebAuthn credential for log in will appear, although a link redirecting to the old page for logging in using a two-factor code will also be present. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add possibility of deleting WebAuthn Credentials Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: disable WebAuthn when an Admin disables 2FA for a user Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: remove ability to disable TOTP leaving only WebAuthn as 2FA Following examples form other platforms like Github, we decided to make Webauthn 2FA secondary to 2FA with TOTP, so that we removed the possibility of removing TOTP authentication only, leaving users with just WEbAuthn as 2FA. Instead, users will have to click on 'Disable 2FA' in order to remove second factor auth. The reason for WebAuthn being secondary to TOPT is that in that way, users will still be able to log in using their code from their phone's application if they don't have their security keys with them – or maybe even lost them. * We had to change a little the flow for setting up TOTP, given that now it's possible to setting up again if you already had TOTP, in order to let users modify their authenticator app – given that now it's not possible for them to disable TOTP and set it up again with another authenticator app. So, basically, now instead of storing the new `otp_secret` in the user, we store it in the session until the process of set up is finished. This was because, as it was before, when users clicked on 'Edit' in the new two-factor methods lists page, but then went back without finishing the flow, their `otp_secret` had been changed therefore invalidating their previous authenticator app, making them unable to log in again using TOTP. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * refactor: fix eslint errors The PR build was failing given that linting returning some errors. This commit attempts to fix them. * refactor: normalize i18n translations The build was failing given that i18n translations files were not normalized. This commits fixes that. * refactor: avoid having the webauthn gem locked to a specific version * refactor: use symbols for routes without '/' * refactor: avoid sending webauthn disabled email when 2FA is disabled When an admins disable 2FA for users, we were sending two mails to them, one notifying that 2FA was disabled and the other to notify that WebAuthn was disabled. As the second one is redundant since the first email includes it, we can remove it and send just one email to users. * refactor: avoid creating new env variable for webauthn_origin config * refactor: improve flash error messages for webauthn pages Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com>
4 years ago
Add WebAuthn as an alternative 2FA method (#14466) * feat: add possibility of adding WebAuthn security keys to use as 2FA This adds a basic UI for enabling WebAuthn 2FA. We did a little refactor to the Settings page for editing the 2FA methods – now it will list the methods that are available to the user (TOTP and WebAuthn) and from there they'll be able to add or remove any of them. Also, it's worth mentioning that for enabling WebAuthn it's required to have TOTP enabled, so the first time that you go to the 2FA Settings page, you'll be asked to set it up. This work was inspired by the one donde by Github in their platform, and despite it could be approached in different ways, we decided to go with this one given that we feel that this gives a great UX. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add request for WebAuthn as second factor at login if enabled This commits adds the feature for using WebAuthn as a second factor for login when enabled. If users have WebAuthn enabled, now a page requesting for the use of a WebAuthn credential for log in will appear, although a link redirecting to the old page for logging in using a two-factor code will also be present. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add possibility of deleting WebAuthn Credentials Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: disable WebAuthn when an Admin disables 2FA for a user Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: remove ability to disable TOTP leaving only WebAuthn as 2FA Following examples form other platforms like Github, we decided to make Webauthn 2FA secondary to 2FA with TOTP, so that we removed the possibility of removing TOTP authentication only, leaving users with just WEbAuthn as 2FA. Instead, users will have to click on 'Disable 2FA' in order to remove second factor auth. The reason for WebAuthn being secondary to TOPT is that in that way, users will still be able to log in using their code from their phone's application if they don't have their security keys with them – or maybe even lost them. * We had to change a little the flow for setting up TOTP, given that now it's possible to setting up again if you already had TOTP, in order to let users modify their authenticator app – given that now it's not possible for them to disable TOTP and set it up again with another authenticator app. So, basically, now instead of storing the new `otp_secret` in the user, we store it in the session until the process of set up is finished. This was because, as it was before, when users clicked on 'Edit' in the new two-factor methods lists page, but then went back without finishing the flow, their `otp_secret` had been changed therefore invalidating their previous authenticator app, making them unable to log in again using TOTP. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * refactor: fix eslint errors The PR build was failing given that linting returning some errors. This commit attempts to fix them. * refactor: normalize i18n translations The build was failing given that i18n translations files were not normalized. This commits fixes that. * refactor: avoid having the webauthn gem locked to a specific version * refactor: use symbols for routes without '/' * refactor: avoid sending webauthn disabled email when 2FA is disabled When an admins disable 2FA for users, we were sending two mails to them, one notifying that 2FA was disabled and the other to notify that WebAuthn was disabled. As the second one is redundant since the first email includes it, we can remove it and send just one email to users. * refactor: avoid creating new env variable for webauthn_origin config * refactor: improve flash error messages for webauthn pages Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com>
4 years ago
Add WebAuthn as an alternative 2FA method (#14466) * feat: add possibility of adding WebAuthn security keys to use as 2FA This adds a basic UI for enabling WebAuthn 2FA. We did a little refactor to the Settings page for editing the 2FA methods – now it will list the methods that are available to the user (TOTP and WebAuthn) and from there they'll be able to add or remove any of them. Also, it's worth mentioning that for enabling WebAuthn it's required to have TOTP enabled, so the first time that you go to the 2FA Settings page, you'll be asked to set it up. This work was inspired by the one donde by Github in their platform, and despite it could be approached in different ways, we decided to go with this one given that we feel that this gives a great UX. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add request for WebAuthn as second factor at login if enabled This commits adds the feature for using WebAuthn as a second factor for login when enabled. If users have WebAuthn enabled, now a page requesting for the use of a WebAuthn credential for log in will appear, although a link redirecting to the old page for logging in using a two-factor code will also be present. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add possibility of deleting WebAuthn Credentials Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: disable WebAuthn when an Admin disables 2FA for a user Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: remove ability to disable TOTP leaving only WebAuthn as 2FA Following examples form other platforms like Github, we decided to make Webauthn 2FA secondary to 2FA with TOTP, so that we removed the possibility of removing TOTP authentication only, leaving users with just WEbAuthn as 2FA. Instead, users will have to click on 'Disable 2FA' in order to remove second factor auth. The reason for WebAuthn being secondary to TOPT is that in that way, users will still be able to log in using their code from their phone's application if they don't have their security keys with them – or maybe even lost them. * We had to change a little the flow for setting up TOTP, given that now it's possible to setting up again if you already had TOTP, in order to let users modify their authenticator app – given that now it's not possible for them to disable TOTP and set it up again with another authenticator app. So, basically, now instead of storing the new `otp_secret` in the user, we store it in the session until the process of set up is finished. This was because, as it was before, when users clicked on 'Edit' in the new two-factor methods lists page, but then went back without finishing the flow, their `otp_secret` had been changed therefore invalidating their previous authenticator app, making them unable to log in again using TOTP. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * refactor: fix eslint errors The PR build was failing given that linting returning some errors. This commit attempts to fix them. * refactor: normalize i18n translations The build was failing given that i18n translations files were not normalized. This commits fixes that. * refactor: avoid having the webauthn gem locked to a specific version * refactor: use symbols for routes without '/' * refactor: avoid sending webauthn disabled email when 2FA is disabled When an admins disable 2FA for users, we were sending two mails to them, one notifying that 2FA was disabled and the other to notify that WebAuthn was disabled. As the second one is redundant since the first email includes it, we can remove it and send just one email to users. * refactor: avoid creating new env variable for webauthn_origin config * refactor: improve flash error messages for webauthn pages Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com>
4 years ago
Add WebAuthn as an alternative 2FA method (#14466) * feat: add possibility of adding WebAuthn security keys to use as 2FA This adds a basic UI for enabling WebAuthn 2FA. We did a little refactor to the Settings page for editing the 2FA methods – now it will list the methods that are available to the user (TOTP and WebAuthn) and from there they'll be able to add or remove any of them. Also, it's worth mentioning that for enabling WebAuthn it's required to have TOTP enabled, so the first time that you go to the 2FA Settings page, you'll be asked to set it up. This work was inspired by the one donde by Github in their platform, and despite it could be approached in different ways, we decided to go with this one given that we feel that this gives a great UX. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add request for WebAuthn as second factor at login if enabled This commits adds the feature for using WebAuthn as a second factor for login when enabled. If users have WebAuthn enabled, now a page requesting for the use of a WebAuthn credential for log in will appear, although a link redirecting to the old page for logging in using a two-factor code will also be present. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: add possibility of deleting WebAuthn Credentials Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: disable WebAuthn when an Admin disables 2FA for a user Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * feat: remove ability to disable TOTP leaving only WebAuthn as 2FA Following examples form other platforms like Github, we decided to make Webauthn 2FA secondary to 2FA with TOTP, so that we removed the possibility of removing TOTP authentication only, leaving users with just WEbAuthn as 2FA. Instead, users will have to click on 'Disable 2FA' in order to remove second factor auth. The reason for WebAuthn being secondary to TOPT is that in that way, users will still be able to log in using their code from their phone's application if they don't have their security keys with them – or maybe even lost them. * We had to change a little the flow for setting up TOTP, given that now it's possible to setting up again if you already had TOTP, in order to let users modify their authenticator app – given that now it's not possible for them to disable TOTP and set it up again with another authenticator app. So, basically, now instead of storing the new `otp_secret` in the user, we store it in the session until the process of set up is finished. This was because, as it was before, when users clicked on 'Edit' in the new two-factor methods lists page, but then went back without finishing the flow, their `otp_secret` had been changed therefore invalidating their previous authenticator app, making them unable to log in again using TOTP. Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com> * refactor: fix eslint errors The PR build was failing given that linting returning some errors. This commit attempts to fix them. * refactor: normalize i18n translations The build was failing given that i18n translations files were not normalized. This commits fixes that. * refactor: avoid having the webauthn gem locked to a specific version * refactor: use symbols for routes without '/' * refactor: avoid sending webauthn disabled email when 2FA is disabled When an admins disable 2FA for users, we were sending two mails to them, one notifying that 2FA was disabled and the other to notify that WebAuthn was disabled. As the second one is redundant since the first email includes it, we can remove it and send just one email to users. * refactor: avoid creating new env variable for webauthn_origin config * refactor: improve flash error messages for webauthn pages Co-authored-by: Facundo Padula <facundo.padula@cedarcode.com>
4 years ago
  1. # frozen_string_literal: true
  2. class UserMailer < Devise::Mailer
  3. layout 'mailer'
  4. helper :accounts
  5. helper :application
  6. helper :instance
  7. helper :statuses
  8. helper :formatting
  9. helper RoutingHelper
  10. def confirmation_instructions(user, token, **)
  11. @resource = user
  12. @token = token
  13. @instance = Rails.configuration.x.local_domain
  14. return unless @resource.active_for_authentication?
  15. I18n.with_locale(@resource.locale || I18n.default_locale) do
  16. mail to: @resource.unconfirmed_email.presence || @resource.email,
  17. subject: I18n.t(@resource.pending_reconfirmation? ? 'devise.mailer.reconfirmation_instructions.subject' : 'devise.mailer.confirmation_instructions.subject', instance: @instance),
  18. template_name: @resource.pending_reconfirmation? ? 'reconfirmation_instructions' : 'confirmation_instructions'
  19. end
  20. end
  21. def reset_password_instructions(user, token, **)
  22. @resource = user
  23. @token = token
  24. @instance = Rails.configuration.x.local_domain
  25. return unless @resource.active_for_authentication?
  26. I18n.with_locale(@resource.locale || I18n.default_locale) do
  27. mail to: @resource.email, subject: I18n.t('devise.mailer.reset_password_instructions.subject')
  28. end
  29. end
  30. def password_change(user, **)
  31. @resource = user
  32. @instance = Rails.configuration.x.local_domain
  33. return unless @resource.active_for_authentication?
  34. I18n.with_locale(@resource.locale || I18n.default_locale) do
  35. mail to: @resource.email, subject: I18n.t('devise.mailer.password_change.subject')
  36. end
  37. end
  38. def email_changed(user, **)
  39. @resource = user
  40. @instance = Rails.configuration.x.local_domain
  41. return unless @resource.active_for_authentication?
  42. I18n.with_locale(@resource.locale || I18n.default_locale) do
  43. mail to: @resource.email, subject: I18n.t('devise.mailer.email_changed.subject')
  44. end
  45. end
  46. def two_factor_enabled(user, **)
  47. @resource = user
  48. @instance = Rails.configuration.x.local_domain
  49. return unless @resource.active_for_authentication?
  50. I18n.with_locale(@resource.locale || I18n.default_locale) do
  51. mail to: @resource.email, subject: I18n.t('devise.mailer.two_factor_enabled.subject')
  52. end
  53. end
  54. def two_factor_disabled(user, **)
  55. @resource = user
  56. @instance = Rails.configuration.x.local_domain
  57. return unless @resource.active_for_authentication?
  58. I18n.with_locale(@resource.locale || I18n.default_locale) do
  59. mail to: @resource.email, subject: I18n.t('devise.mailer.two_factor_disabled.subject')
  60. end
  61. end
  62. def two_factor_recovery_codes_changed(user, **)
  63. @resource = user
  64. @instance = Rails.configuration.x.local_domain
  65. return unless @resource.active_for_authentication?
  66. I18n.with_locale(@resource.locale || I18n.default_locale) do
  67. mail to: @resource.email, subject: I18n.t('devise.mailer.two_factor_recovery_codes_changed.subject')
  68. end
  69. end
  70. def webauthn_enabled(user, **)
  71. @resource = user
  72. @instance = Rails.configuration.x.local_domain
  73. return unless @resource.active_for_authentication?
  74. I18n.with_locale(@resource.locale || I18n.default_locale) do
  75. mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_enabled.subject')
  76. end
  77. end
  78. def webauthn_disabled(user, **)
  79. @resource = user
  80. @instance = Rails.configuration.x.local_domain
  81. return unless @resource.active_for_authentication?
  82. I18n.with_locale(@resource.locale || I18n.default_locale) do
  83. mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_disabled.subject')
  84. end
  85. end
  86. def webauthn_credential_added(user, webauthn_credential)
  87. @resource = user
  88. @instance = Rails.configuration.x.local_domain
  89. @webauthn_credential = webauthn_credential
  90. return unless @resource.active_for_authentication?
  91. I18n.with_locale(@resource.locale || I18n.default_locale) do
  92. mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_credential.added.subject')
  93. end
  94. end
  95. def webauthn_credential_deleted(user, webauthn_credential)
  96. @resource = user
  97. @instance = Rails.configuration.x.local_domain
  98. @webauthn_credential = webauthn_credential
  99. return unless @resource.active_for_authentication?
  100. I18n.with_locale(@resource.locale || I18n.default_locale) do
  101. mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_credential.deleted.subject')
  102. end
  103. end
  104. def welcome(user)
  105. @resource = user
  106. @instance = Rails.configuration.x.local_domain
  107. return unless @resource.active_for_authentication?
  108. I18n.with_locale(@resource.locale || I18n.default_locale) do
  109. mail to: @resource.email, subject: I18n.t('user_mailer.welcome.subject')
  110. end
  111. end
  112. def backup_ready(user, backup)
  113. @resource = user
  114. @instance = Rails.configuration.x.local_domain
  115. @backup = backup
  116. return unless @resource.active_for_authentication?
  117. I18n.with_locale(@resource.locale || I18n.default_locale) do
  118. mail to: @resource.email, subject: I18n.t('user_mailer.backup_ready.subject')
  119. end
  120. end
  121. def warning(user, warning)
  122. @resource = user
  123. @warning = warning
  124. @instance = Rails.configuration.x.local_domain
  125. @statuses = @warning.statuses.includes(:account, :preloadable_poll, :media_attachments, active_mentions: [:account])
  126. I18n.with_locale(@resource.locale || I18n.default_locale) do
  127. mail to: @resource.email, subject: I18n.t("user_mailer.warning.subject.#{@warning.action}", acct: "@#{user.account.local_username_and_domain}")
  128. end
  129. end
  130. def appeal_approved(user, appeal)
  131. @resource = user
  132. @instance = Rails.configuration.x.local_domain
  133. @appeal = appeal
  134. I18n.with_locale(@resource.locale || I18n.default_locale) do
  135. mail to: @resource.email, subject: I18n.t('user_mailer.appeal_approved.subject', date: l(@appeal.created_at))
  136. end
  137. end
  138. def appeal_rejected(user, appeal)
  139. @resource = user
  140. @instance = Rails.configuration.x.local_domain
  141. @appeal = appeal
  142. I18n.with_locale(@resource.locale || I18n.default_locale) do
  143. mail to: @resource.email, subject: I18n.t('user_mailer.appeal_rejected.subject', date: l(@appeal.created_at))
  144. end
  145. end
  146. def suspicious_sign_in(user, remote_ip, user_agent, timestamp)
  147. @resource = user
  148. @instance = Rails.configuration.x.local_domain
  149. @remote_ip = remote_ip
  150. @user_agent = user_agent
  151. @detection = Browser.new(user_agent)
  152. @timestamp = timestamp.to_time.utc
  153. I18n.with_locale(@resource.locale || I18n.default_locale) do
  154. mail to: @resource.email, subject: I18n.t('user_mailer.suspicious_sign_in.subject')
  155. end
  156. end
  157. end